home *** CD-ROM | disk | FTP | other *** search
- #ifndef VMS
- ERROR -- CKVFIO.C is used only on the OpenVMS(tm) Operating System
- #endif /* VMS */
-
- #ifdef __ALPHA
- # define CKVFIO_OS_ARCH_STRING " OpenVMS(tm) AXP(tm)";
- /* do nothing */
- #else
- # ifdef VAX
- # module ckvfio "2.0-101"
- # define CKVFIO_OS_ARCH_STRING " OpenVMS(tm) VAX(tm)";
- # else
- # ifdef __GNUC__
- # define CKVFIO_OS_ARCH_STRING " OpenVMS(tm) VAX(tm) (GCC)";
- # else
- # ERROR -- CKVTIO.C unknown architecture, neither VAX(tm) nor AXP(tm)
- # endif /* __GNUC__ */
- # endif /* VAX */
- #endif /* __ALPHA */
-
- char *ckzv = "File support, 2.0(101), 8 Aug 93";
- char *ckzsys = CKVFIO_OS_ARCH_STRING;
-
- /* lt. 1992-10-08 End
- */
-
- /* C K V F I O -- Kermit file system support for VAX/VMS. */
-
- /*
- Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
- Columbia University Academic Information Systems, New York City.
-
- Copyright (C) 1985, 1993, Trustees of Columbia University in the City of New
- York. The C-Kermit software may not be, in whole or in part, licensed or
- sold for profit as a software product itself, nor may it be included in or
- distributed with commercial products or otherwise distributed by commercial
- concerns to their clients or customers without written permission of the
- Office of Kermit Development and Distribution, Columbia University. This
- copyright notice must not be removed, altered, or obscured.
- */
-
- /*
- Originally adapted to VMS by:
- Stew Rubenstein, Harvard University Chemical Labs, 1985,
- Contributors:
- Frank da Cruz (fdc), Columbia University Center, New York, NY (1985-93)
- Stew Rubenstein, Harvard University Chemical Labs, Cambridge, MA (1985)
- Martin Minow (MM), Digital Equipment Corporation, Maynard MA (1985)
- Dan Schullman (DS), Digital Equipment Corporation, Maynard MA (1985)
- Mark Buda (MAB), Digital Equipment Corporation, Nashua, NH (1989-90)
- Terry Kennedy (TMK), St. Peter's College, Jersey City, NJ (1990-92)
- William Bader (WB), Lehigh University, Bethlehem, PA (1990-92)
- Gary Mussar (GM), Bell-Northern Research, Ottawa, Canada (1991)
- James Sturdevant (JS) (1992)
- */
- /* Edit history
- * 003 20-Mar-85 MM fixed fprintf bug in zsout.c
- * 004 21-Mar-84 MM create text files in variable-stream.
- * 005 8-May-85 MM filled in zkself (not tested), fixed other minor bugs
- * 006 5-Jul-85 DS handle version number in zltor, zrtol
- * 007 11-Jul-85 fdc fix zclose() to give return codes
- * 008 19-Mar-86 fdc Fix system() for "!", zopeni() for REMOTE commands.
- * 008 17-Sep-87 fdc Define PWDCMD.
- * 009 (???)
- * 010 24-Jan-88 fdc Add zgtdir() function, even tho it doesn't work...
- * 011 14-Feb-89 mab Make zgtdir() work in V2/V3 C envirements,
- * Make zkself work using delprc() using Will Wood's changes.
- * 012 26-Feb-89 mab Add function that searches for kermit.ini file in various
- * ways
- * 013 05-Mar-89 mab Add Barry Archers enhancements/fixes.
- * 014 15-Mar-89 mab Check for non-null data, not array of pointers in
- * zkermini
- * 015 04-Apr-89 mab Add latent support for attribute packet. Clean up
- * file name translation code.
- * 016 05-Apr-89 mab Add PWP code to optimize packetizing.
- * 017 16-Apr-89 mab PWP changes broke REMOTE command. Fixed.
- * 018 18-Apr-89 mab #ifdef chkfn. This removes a lot of overhead.
- * Add code to gtdir() for V4.x.
- * 019 12-Jun-89 mab Add PWP's encode logic
- * 020 09-Jul-89 mab Add logic to check for system() availability
- * 021 10-Jul-89 mab Fix SHOW USER USERNAME. Added space after 'SHOW USER'.
- * 022 27-Sep-89 mab Added zmail/zprint, plus added changes from CKUFIO.C
- * 023 01-Dec-89 mab Add RMS file support
- * 024 20-Jul-90 wb Add support for old VAX C & VMS versions + zstrip & rename
- * 025 29-Jul-90 tmk Change space command to show avail, not used (match spec)
- * 026 29-Jul-90 tmk Hack out the RMS stuff - it can come back when it works
- * 027 29-Jul-90 tmk Likewise the VMS V3 stuff - ancient history
- * 028 29-Jul-90 tmk Replace the attribute stuff. It now works.
- * 029 31-Jul-90 tmk Fix CWD command (via hack)
- * 030 31-Jul-90 tmk Fix assorted bugs preventing remote commands from working
- * 031 31-Jul-90 tmk Correctly handle interrupted remote commands
- * 032 04-Aug-90 tmk Start work on full RMS support for input files
- * 033 04-Aug-90 tmk Tack LF on end of subprocess output lines
- * 034 04-Aug-90 tmk Complete work on full RMS support for input files
- * 035 04-Aug-90 tmk Add support for Fortran CC, fill in recfm data
- * 036 05-Aug-90 tmk Add trailing CRLF on print format files
- * 037 12-Aug-90 tmk Start work on full RMS support for output files
- * 038 12-Aug-90 tmk Honor first free byte (FFB) on SENDs
- * 039 13-Aug-90 tmk Finished first cut of full RMS support for output files
- * 040 29-Sep-90 tmk Add iswild() from FDC for edit 157
- * 041 06-Oct-90 tmk Add filetype IMAGE support for outbound transfers. Note
- * that this doesn't currently work as the receiver overrides
- * it (must talk to fdc).
- * 042 06-Oct-90 tmk Make logfiles MRS=80. Being able to edit them outweighs
- * any use for un-split lines.
- * 043 17-Oct-90 wb Make zclosf() remove delete mailboxes & deassign channels
- * used to talk to the subprocess, so quotas are not used
- * up after repeated mailbox use (installed by fdc).
- * 044 19-Oct-90 fdc Changed zxcmd() to use the fp[] arrays in the normal way,
- * and zsyscmd to call zxcmd(ZIFILE) rather than
- * zxcmd(ZSYSFN). Got rid of all calls to system(), used
- * zsyscmd() instead, so commands like DIR could be
- * interrupted. Made zoutdump() return(-1) rather than
- * exit() when "line too long for buffer", and increased
- * line output buffer from 1K to 4K.
- * 045 01-Nov-90 tmk Corrected behavior of error check on $create call so a
- * file supersede would work properly.
- * 046 01-Nov-90 tmk Clone binary flag to ofile_bmode so we have a consistent
- * view of this flag during file operations - the binary flag
- * tends to toggle when we don't want/expect it to.
- * 047 01-Nov-90 tmk Make IMAGE mode work. Note that image mode is only used
- * when VMS is sending a file, and includes all record
- * control characters not normally sent. Only useful in
- * unusual circumstances.
- * 048 01-Nov-90 tmk Remove spurious \n from zsoutl() which caused debug logs
- * to have spurious <CR>'s when viewed with editors.
- * 049 02-Nov-90 fdc Adapt to dynamic allocation of file i/o buffers. Changes
- * are within #ifdef DYNAMIC..#else..#endif brackets.
- * 050 02-Nov-90 fdc Make zsyscmd() close inferior process.
- * 051 ??-???-?? ??? Add ckermit_init logical, return 0 on wildcard operations.
- * 052 24-Dec-90 tmk Fix performance problems after 32Kb w/ ASCII receives, fix
- 2-nulls-per-32Kb in binary mode bug (actually in ckcker.h,
- this is a placeholder).
- * 053 13-Jan-91 tmk Add support for SET FILE RECORD-LENGTH.
- * 054 14-Jan-91 tmk Fix cases of /x/CR/LF/y/ and /x/CR/LF/y/CR/LF/ in ASCII
- * file receives.
- * 055 16-Jan-91 tmk Log requested file type to debug log when receiving.
- * 056 16-Jan-91 tmk Add support for all zstime() functions.
- * 057 17-Jan-91 tmk Add support for zchkspa() function.
- * 058 17-Jan-91 tmk Move debug() call into if clause in zxpand, per fdc.
- * 059 18-Jan-91 tmk Support remote (DECnet) file accesses.
- * 060 18-Jan-91 tmk Fix READ command.
- * 061 30-Jan-91 tmk Support creation of UNDEFINED file types for brain-dead
- * BASIC implementation.
- * 062 30-Jan-91 tmk Fix REMOTE commands when VERIFY is set.
- * 063 29-Mar-91 tmk Add padding factor for received text files to accomodate
- * space taken up by record delimiters (per fdc).
- * 064 29-Mar-91 gm Remove unnecessary mem-mem moves during ASCII receives.
- * (Installed by tmk. To back out, #define OLD_WAY).
- * 065 30-Mar-91 tmk First pass at implementing LABELED. Send only, dummy
- * data records.
- * 066 02-Apr-91 tmk Finish first pass at LABELED. Send VMS filename, attri-
- * butes. Still need ACL's, "hidden" char. longword, recep-
- * tion.
- * 067 09-Apr-91 tmk LABELED bugfixes - VMSFILE is 70 bytes, not 74, use the
- * xab$w_lrl field instead of rab$w_rsz, fab$w_deq instead
- * of xab$w_rsz, fab$b_bks instead of xab$b_bkz, always pro-
- * cess an even multiple of 512 bytes when LABELED.
- * 068 14-Apr-91 tmk Don't use C definition of fab$b_journal as it doesn't ex-
- * ist before C V3.1. Compute it ourselves instead.
- * 069 15-Apr-91 tmk Initial work on retrieving ACL information for LABELED.
- * 070 16-Apr-91 tmk Make edits 066-069 compatible with DECnet.
- * 071 21-May-91 tmk Address R. Weiner QAR item 2 (filesize).
- * 072 21-Jun-91 tmk Check (and prohibit) spawns from captive accounts.
- * 073 21-Jun-91 tmk Fix session logging (for Charlie Luce/DECUServe).
- * 074 21-Jun-91 tmk Rework 071 to only apply to SPAWN/PUSH and not to the
- * pseudo-builtins like DEL, SPACE, WHO, PWD, etc.
- * 075 21-Jun-91 tmk Fix possible endless loop when flushing output file in
- * zclosf() after zoutdump() error.
- * 076 21-Jun-91 tmk First pass on handling inbound LABELED files.
- * 077 14-Nov-91 tmk Fix zprint(), zmail() (need to use system() for these).
- * This is a partial backout of 044.
- * 078 14-Nov-91 tmk Various cleanups. Delete files after successful mailing
- * or printing, remove dead code inside #ifdef COMMENT and
- * #ifdef OLD_WAY, fix typo in spawning message, make sure
- * all source lines < 80 chars.
- * 079 22-Nov-91 fdc Change zmail(), zprint() error return values to improve
- * error reporting.
- * 080 18-Jan-92 tmk Fix REMOTE so output from a remote command correctly dis-
- * plays on terminal. This has been broken since 040 or so.
- * 081 10-Jun-92 tmk Add William Bader's fix for fixed-length files which have
- * record attributes.
- * 082 03-Jul-92 tmk Fix really bad bug introduced in 081 (which made *all*
- * fixed-format files be sent as text).
- * 083 15-Jul-92 jah Fix fencepost error in zoutdump when line breaks at 32K.
- * 084 03-Aug-92 fdc Remove current directory from init file search.
- * 085 26-Aug-92 tmk Add Bernd Onasch's fix for fgen().
- * 086 28-Aug-92 tmk Fix bug reported by Bill Hoelzer where C-K would execute
- * a file named "." as a C-K initialization file.
- * 087 04-Sep-92 tmk Fix bug reported by Chuck McMichael where C-K would not
- * set the FFB properly when receiving a labeled file which
- * did not have the FFB on a record boundary.
- * 088 09-Sep-92 tmk Fix Hunter Goatley's problem with SPAWN command ignoring
- * Ctrl-C.
- * 089 11-Sep-92 js Fixed malloc() in zmail().
- * 090 28-Oct-92 tmk Fix null-byte error introduced by 087. Gee, this looked
- * so simple when I designed it.
- * 091 02-Nov-92 tmk Start work on fixing spawn/push/remote commands, due to
- * popular whining.
- * 092 03-Nov-92 tmk Finish up initial 091 work. Vote for Kermit!
- * 093 03-Nov-92 fdc Change zkermini() to work with "-y" command-line option.
- * 094 04-Nov-92 tmk Make zxpand() not return all files if given null string.
- * 095 05-Nov-92 fdc Make zxcmd(), zclose(), etc, handle ZRFILE (OPEN !READ).
- * 096 17-Feb-93 fdc prevent zopeno from calling zstime if date struct is NULL,
- * and add support for ZMFILE (misc output file).
- * 097 08-Apr-93 tmk Correctly handle "international VMS" which uses <> instead
- * of [] for directory delimiters.
- * 098 16-May-93 fdc ANSIfication for GNU CC, from James Sturdevant, plus
- * add FAB$M_PRN to list of text-file types, for VMS batch
- * logs.
- * 099 07-Jun-93 fdc Fix calculation of file size in zchki(), fix declaration
- * of mbxnam[] (add one to size) to prevent overflow, which
- * would result in failure of server to respond to REMOTE
- * directory, etc. Both fixes from Bill Glass.
- * 100 21-Jun-93 fdc file_date[] and attr_date[] declarations in zstime()
- * changed from long to unsigned long to prevent signed date
- * comparisons, which could prevent SET FILE COLLISION
- * UPDATE from working. From James Sturdevant.
- * 101 8-Aug-93 fdc Add types to all function declarations.
- */
-
- /* Definitions of some VMS system commands */
-
- char *DIRCMD = "directory "; /* For directory listing */
- char *DIRCM2 = "directory "; /* For directory listing, no args */
- char *DELCMD = "delete "; /* For file deletion */
- char *TYPCMD = "type "; /* For typing a file */
- char *SPACMD = "show quota "; /* Space/quota of current directory */
- char *SPACM2 = "show quota "; /* Space/quota of specified dir */
- char *WHOCMD = "show users "; /* For seeing who's logged in */
- char *PWDCMD = "show default "; /* For seeing current directory */
-
- /*
- Functions (n is one of the predefined file numbers from ckermi.h):
-
- zopeni(n,name) -- Opens an existing file for input.
- zopeno(n,name) -- Opens a new file for output.
- zclose(n) -- Closes a file.
- zchin(n) -- Gets the next character from an input file.
- zsout(n,s) -- Write a null-terminated string to output file, buffered.
- zsoutl(n,s) -- Like zsout, but appends a line terminator.
- zsoutx(n,s,x) -- Write x characters to output file, unbuffered.
- zchout(n,c) -- Add a character to an output file, unbuffered.
- zchki(name) -- Check if named file exists and is readable, return size.
- zchko(name) -- Check if named file can be created.
- zchkspa(name,n) -- Check if n bytes available to create new file, name.
- znewn(name,s) -- Make a new unique file name based on the given name.
- zdelet(name) -- Delete the named file.
- zxpand(string) -- Expands the given wildcard string into a list of files.
- znext(string) -- Returns the next file from the list in "string".
- zxcmd(n,cmd) -- Execute the command in a lower fork on file number n.
- zclosf() -- Close input file associated with zxcmd()'s lower fork.
- zrtol(n1,n2) -- Convert remote filename into local form.
- zltor(n1,n2) -- Convert local filename into remote form.
- zchdir(dirnam) -- Change working directory.
- zhome() -- Return pointer to home directory name string.
- zkself() -- Log self out
- zsattr(struc zattr *) -- Return attributes for file which is being sent.
- zkermini(n1,n2) -- Find kermit.ini using default scanning process
- */
-
- /* Includes */
-
- #include "ckcdeb.h"
- #include "ckcasc.h"
- #include "ckcker.h"
- #include "ckvvms.h"
- #include <stdio.h>
- #include <stat.h>
- #include <ctype.h>
- #include <rms.h>
- #include <ssdef.h>
- #include <descrip.h>
- #include <dvidef.h>
- #include <dcdef.h>
- #include <iodef.h>
- #include <jpidef.h>
- #include <signal.h>
- #include <string.h>
- #include <syidef.h>
- #include <uaidef.h>
-
- #define MAXWLD 500 /* Maximum wildcard filenames */
-
- /* external def. of things used in buffered file input and output */
-
- #ifdef DYNAMIC
- extern CHAR *zinbuffer, *zoutbuffer;
- #else
- extern CHAR zinbuffer[], zoutbuffer[];
- #endif /* DYNAMIC */
-
- extern CHAR *zinptr, *zoutptr;
- extern int zincnt, zoutcnt;
- extern int binary;
- extern int frecl;
- extern int rcflag;
-
- extern long vernum;
-
- /* Declarations */
-
- FILE *fp[ZNFILS] = { /* File pointers */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
- };
-
- static long iflen = -1; /* Input file length */
- static long oflen = -1; /* Output file length */
- static int fcount; /* Number of files in wild group */
- static char nambuf[255]; /* maximum size of a file spec */
- static char cwdbuf[NAM$C_MAXRSS];
- static struct iosb_struct tmpiosb; /* For QIOW */
-
- extern unsigned long vms_status; /* Used by CHECK_ERR */
-
- static int cflag; /* Flag indicating console in use */
-
- char *getenv(), *strcpy(); /* For finding home directory */
-
- /* static */ /* Not static any more! */
- char *mtchs[MAXWLD], /* Matches found for filename */
- **mtchptr; /* Pointer to current match */
-
- static unsigned short mbx_chan; /* Mailbox chan for REMOTE commands */
- static int subprocess_input = 0, sub_count;
- static char *sub_ptr, sub_buf[SUB_BUF_SIZE];
-
- #define SUPERSAFE /* For safe subprocesses */
- static unsigned long sub_pid;
-
- /*
- * Structures for input (SEND) file
- */
-
- static struct FAB fab_ifile;
- static struct RAB rab_ifile;
- static struct XABDAT xabdat_ifile;
- static struct XABFHC xabfhc_ifile;
- static struct XABPRO xabpro_ifile;
- static struct XABALL xaball_ifile;
- static int ifile_bmode;
- static int ifile_bcount;
- static char aclbuf[512];
- static unsigned long uchar = 0;
-
- /*
- * Structures for output (RECEIVE) file
- */
-
- static struct FAB fab_ofile;
- static struct RAB rab_ofile;
- static struct XABDAT xabdat_ofile;
- static struct XABFHC xabfhc_ofile;
- static struct XABPRO xabpro_ofile;
- static struct XABALL xaball_ofile;
- static struct XABRDT xabrdt_ofile;
- static int ofile_dump;
- static int ofile_bmode;
- static int ofile_lblopts;
- static int ofile_lblproc;
- static char revdat[8];
- static unsigned short revnum;
- static char ofile_vmsname[255];
- static char ofile_vmsacl[512];
- static int ofile_acllen;
- static short ofile_ffb;
-
- /*
- * Common RMS items
- */
- static unsigned long int rms_sts;
-
- /* I S W I L D -- Tells whether filespec "str" is wild */
- /* Returns 0 if not wild, 1 if wild */
-
- int
- iswild(str) char *str; {
- char c;
- while ((c = *str++) != '\0')
- if (c == '*' || c == '%') return(1);
- return(0);
- }
-
- /* Z K S E L F -- Log self out. */
-
- VOID
- zkself() {
- unsigned long int rms_s;
-
- rms_s = sys$delprc(0,0);
- exit(rms_s == SS$_NORMAL);
- }
-
- /* Z O P E N I -- Open an existing file for input. */
-
- int
- zopeni(n,name) int n; char *name; {
- debug(F111," zopeni",name,n);
- debug(F101," fp","",(int) fp[n]);
- if (chkfn(n)) return(0);
- if (n == ZSYSFN) { /* Input from a system function? */
- debug(F110," zopeni called with ZSYSFN, failing!",name,0);
- *nambuf = '\0'; /* No filename. */
- return(0); /* fail. */
- }
- zincnt = 0; /* Initializing these couldn't hurt */
- zinptr = zinbuffer;
- if (n == ZSTDIO) { /* Standard input? */
- if (isatty(0)) {
- ermsg("?Terminal input not allowed\n");
- debug(F110," zopeni attempted input from unredirected stdin","",0);
- return(0);
- }
- fp[ZIFILE] = stdin;
- return(1);
- }
- /*
- * We open the file but waffle on the access mode we're going to use. We then
- * inspect the file characteristics to see if the organization is fixed or un-
- * defined. If it is, we convert to block mode operation. This is needed since
- * VMS maintains a "first free byte" field to tell us how much of the last rec-
- * ord really contains data, but won't terminate reads at that point. Thus, if
- * we want to SEND the exact same file we RECEIVEd, we have to honor the FFB
- * internally.
- */
- if (n == ZIFILE || n == ZRFILE) {
- ifile_bmode = 0;
- ifile_bcount = 0;
- fab_ifile = cc$rms_fab;
- fab_ifile.fab$b_fac = FAB$M_BRO | FAB$M_GET;
- /*
- * Some non-VMS DECnet implementations don't allow switching modes, so set
- * block-I/O only mode if the user said SET FILE TYPE IMAGE or LABELED.
- */
- if (binary == XYFT_I || binary == XYFT_L)
- fab_ifile.fab$b_fac = FAB$M_BIO | FAB$M_GET;
- fab_ifile.fab$l_fna = name;
- fab_ifile.fab$b_fns = strlen(name);
- fab_ifile.fab$l_xab = (char *)&xabdat_ifile;
- rab_ifile = cc$rms_rab;
- rab_ifile.rab$l_fab = &fab_ifile;
- xabdat_ifile = cc$rms_xabdat;
- xabdat_ifile.xab$l_nxt = (char *)&xabfhc_ifile;
- xabfhc_ifile = cc$rms_xabfhc;
- xabfhc_ifile.xab$l_nxt = (char *)&xabpro_ifile;
- xabpro_ifile = cc$rms_xabpro;
- memset(&aclbuf, 0, sizeof(aclbuf));
- xabpro_ifile.xab$l_aclsts = SS$_NORMAL; /* Oh Joy! DECnet */
- xabpro_ifile.xab$l_aclbuf = (char *)&aclbuf;
- xabpro_ifile.xab$w_aclsiz = sizeof(aclbuf);
- xabpro_ifile.xab$l_aclctx = 0;
- xabpro_ifile.xab$l_nxt = (char *)&xaball_ifile;
- xaball_ifile = cc$rms_xaball;
-
- rms_sts = sys$open(&fab_ifile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zopeni $open failed, status","",rms_sts);
- debug(F101," zopeni $open failed, stv","",fab_ifile.fab$l_stv);
- return(0);
- }
- if (!(xabpro_ifile.xab$l_aclsts & 1)) {
- if (xabpro_ifile.xab$l_aclsts != SS$_ACLEMPTY) {
- debug(F101," zopeni $open ACL failed, status","",
- xabpro_ifile.xab$l_aclsts);
- return(0);
- }
- }
- /*
- * We have the file opened. See if it's fixed or undefined format...
- */
- if (fab_ifile.fab$b_rfm == FAB$C_UDF) {
- debug(F100," zopeni undefined file format - using blk I/O","",0);
- ifile_bmode = 1;
- }
- if (fab_ifile.fab$b_rfm == FAB$C_FIX) {
- if ((fab_ifile.fab$b_rat & (FAB$M_FTN | FAB$M_CR | FAB$M_PRN))
- == 0) {
- debug(F100," zopeni fixed file format - using blk I/O","",0);
- ifile_bmode = 1;
- }
- }
- debug(F101," zopeni binary flag at open","",binary);
- if (binary == XYFT_I) {
- debug(F100," zopeni using IMAGE mode by user request","",0);
- ifile_bmode = 1;
- }
- if (binary == XYFT_L) {
- debug(F100," zopeni using LABELED mode by user request","",0);
- ifile_bmode = 2;
- }
- rab_ifile.rab$l_rop = 0;
- rms_sts = sys$connect(&rab_ifile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zopeni $connect failed, status","",rms_sts);
- return(0);
- }
- debug(F100," zopeni RMS operations completed ok","",0);
- fp[n] = fopen("NLA0:","r"); /* it wants a fp, give it one */
- zincnt = 0; /* reset input buffer */
- if (binary == XYFT_L)
- do_label_send(name); /* make a file label */
- return(1);
- }
- zincnt = 0; /* Reset input buffer */
- fp[n] = fopen(name,"r"); /* Real file. */
- debug(F111," zopeni", name, (int) fp[n]);
- if (fp[n] == NULL) perror("zopeni");
- return((fp[n] != NULL) ? 1 : 0);
- }
-
- /* Z O P E N O -- Open a new file for output. */
-
- int
- zopeno(n,name,zz,fcb)
- int n; char *name; struct zattr *zz; struct filinfo *fcb; {
-
- /* As of Version 5A, the attribute structure and the file information */
- /* structure are included in the arglist. */
-
- int fildes;
-
- if (n != ZDFILE)
- debug(F111," zopeno",name,n);
- if (chkfn(n) != 0) return(0);
-
- zoutcnt = 0; /* (PWP) reset output buffer */
- zoutptr = zoutbuffer;
- cflag = 0; /* default to not using console */
-
- /*
- * Open Terminal or STDIO
- */
-
- if ((n == ZCTERM) || (n == ZSTDIO)) {
- fp[ZOFILE] = stdout;
- cflag = 1; /* say using console */
- if (n != ZDFILE)
- debug(F101," fp[]=stdout", "", (int) fp[n]);
- return(1);
- }
-
- /*
- * Open Debug, Transaction, Packet, Session logfile, or a Write file
- * The only other possibility at this point is the output file, so we test that
- */
-
- if (n != ZOFILE) {
- if (n != ZSFILE)
- fildes = creat(name, 0, "rat=cr", "rfm=var", "mrs=80");
- else
- fildes = creat(name, 0, "ctx=stm");
- fp[n] = (fildes == -1) ? NULL : fdopen(fildes, "w");
- if (fp[n] == NULL)
- perror(name);
- return((fp[n] != NULL) ? 1 : 0);
- }
-
- /*
- * Open a file to store data being RECEIVEd
- */
-
- if (n == ZOFILE) {
- switch (binary) {
- case XYFT_T:
- debug(F100," zopeno receiving TEXT file","",0);
- break;
- case XYFT_B:
- debug(F100," zopeno receiving BINARY file","",0);
- break;
- case XYFT_I:
- debug(F100," zopeno receiving IMAGE file-program bug!","",0);
- break;
- case XYFT_L:
- debug(F100," zopeno receiving LABELED file","",0);
- break;
- case XYFT_U:
- debug(F100," zopeno receiving UNDEFINED file","",0);
- break;
- default:
- debug(F101," zopeno unknown file type","",binary);
- }
- ofile_bmode = binary;
- ofile_dump = 0;
- ofile_ffb = -1;
- fab_ofile = cc$rms_fab;
- fab_ofile.fab$l_fna = name;
- fab_ofile.fab$b_fns = strlen(name);
- fab_ofile.fab$l_fop = FAB$M_MXV;
- if (ofile_bmode) {
- fab_ofile.fab$b_fac = FAB$M_BIO;
- debug(F101," zopeno using record size","",frecl);
- fab_ofile.fab$w_mrs = frecl;
- if (ofile_bmode == XYFT_U)
- fab_ofile.fab$b_rfm = FAB$C_UDF;
- else
- fab_ofile.fab$b_rfm = FAB$C_FIX;
- } else {
- fab_ofile.fab$b_rat = FAB$M_CR;
- fab_ofile.fab$b_rfm = FAB$C_VAR;
- }
- fab_ofile.fab$b_shr = FAB$M_NIL;
- fab_ofile.fab$l_xab = (char *)&xabdat_ofile;
- rab_ofile = cc$rms_rab;
- rab_ofile.rab$l_fab = &fab_ofile;
- xabdat_ofile = cc$rms_xabdat;
- xabdat_ofile.xab$l_nxt = (char *)&xabfhc_ofile;
- xabfhc_ofile = cc$rms_xabfhc;
- if (zz)
- zstime(name, zz, 2); /* set creation date */
- if (ofile_bmode == XYFT_L) { /* defer open if labeled */
- ofile_lblproc = 0; /* haven't processed labels yet */
- ofile_lblopts = fcb->lblopts;
- debug(F101," zopeno lblopts","",ofile_lblopts);
- debug(F100," zopeno RMS operations deferred","",0);
- } else {
- rms_sts = sys$create(&fab_ofile);
- if (!(rms_sts & 1)) {
- debug(F101," zopeno $create failed, status","",rms_sts);
- return(0);
- }
- rms_sts = sys$connect(&rab_ofile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zopeno $connect failed, status","",rms_sts);
- return(0);
- }
- debug(F100," zopeno RMS operations completed ok","",0);
- }
- fp[n] = fopen("NLA0:","r"); /* it wants a fp, give it one */
- return(1);
- }
- }
-
- /* Z C L O S E -- Close the given file. */
-
- /* Returns 0 if arg out of range, 1 if successful, -1 if close failed. */
-
- int
- zclose(n) int n; {
- int x=0;
-
- debug(F101," zclose","",n);
- if (chkfn(n) < 1) return(0);
-
- /* If this is the subprocess file, close it to flush output */
-
- if ((n == ZIFILE || (n == ZRFILE)) && (subprocess_input != 0)) {
- debug(F100, "zclose calling zclosf", "", 0);
- return (zclosf(n));
- }
-
- /* Input file */
-
- if (n == ZIFILE) {
- rms_sts = sys$close(&fab_ifile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zclose $close failed, status","",rms_sts);
- return(-1);
- }
- debug(F100," zclose RMS operations completed ok","",0);
- x = fclose(fp[n]); /* close the dummy file */
- fp[n] = NULL; /* and mark it so */
- iflen = -1;
- return(1);
- }
-
- /* Output file */
- /* This can probably be combined with the ZIFILE stuff later */
-
- if (n == ZOFILE) {
- ofile_dump = 1; /* force complete dump */
- while (zoutcnt != 0) {
- rms_sts = zoutdump(); /* flush buffers to disk */
- if (rms_sts != 0)
- return(-1); /* in case of error */
- }
-
- if (ofile_bmode == XYFT_L) { /* update revisions if labeled */
- debug(F100," zclose updated labeled revision count","",0);
- memmove(&xabrdt_ofile.xab$q_rdt, revdat, 8);
- memmove(&xabrdt_ofile.xab$w_rvn, &revnum, 2);
- }
-
- if (cflag != 1) {
- rms_sts = sys$close(&fab_ofile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zclose $close failed, status","",rms_sts);
- return(-1);
- }
- x = fclose(fp[n]); /* close the dummy file */
- } else {
- cflag = 0;
- }
- debug(F100," zclose RMS operations completed ok","",0);
- fp[n] = NULL; /* and mark it so */
- iflen = -1;
- return(1);
- }
-
- /* Other kind of file */
-
- if ((fp[n] != stdout) && (fp[n] != stdin))
- x = fclose(fp[n]);
- fp[n] = NULL;
- iflen = -1; /* Invalidate file length */
- debug(F101," x","",x);
- if (x == EOF) /* if we got a close error */
- return (-1);
- else
- return (1);
- }
-
- int
- get_subprc_line() {
- struct iosb_struct subiosb;
-
- unsigned int sts;
- /*
- * Someone complained that subprocess deletion would hang the Kermit server.
- * This can be triggered by sending something silly like REMOTE HOST STOP/ID=0.
- * If SUPERSAFE is defined we will check to make sure the subprocess still
- * exists before every read from the mailbox. This will slow things down a bit,
- * but should stop the "C-Kermit just dies" reports.
- */
- #ifdef SUPERSAFE
- unsigned short pid;
-
- struct itmlstdef {
- short int buflen;
- short int itmcod;
- char *bufaddr;
- long int *retlen;
- };
- struct itmlstdef itmlst[] = {
- 4, JPI$_PID, (char *)&pid, 0,
- 0, 0, 0, 0
- };
- sts = sys$getjpiw(0, &sub_pid, 0, &itmlst, 0, 0, 0);
-
- debug(F101,"get_subprc_line sys$getjpiw status", "", sts);
- if (sts == SS$_NONEXPR)
- return(-1);
- #endif /* SUPERSAFE */
-
- sts = sys$qiow(QIOW_EFN, mbx_chan, IO$_READVBLK, &subiosb, 0, 0, sub_buf,
- sizeof(sub_buf), 0, 0, 0, 0);
-
- debug(F101,"get_subprc_line sys$qiow status", "", sts);
- if (sts != SS$_NORMAL)
- return(-1);
-
- debug(F101,"get_subprc_line sys$qiow subiosb.status", "", subiosb.status);
- if (subiosb.status == SS$_ENDOFFILE)
- return(-1);
-
- if (subiosb.status != SS$_NORMAL)
- return(-1);
-
- sub_buf[subiosb.size] = '\r';
- sub_buf[subiosb.size + 1] = '\n';
- sub_buf[subiosb.size + 2] = '\0';
- sub_count = subiosb.size + 2;
- sub_ptr = sub_buf;
-
- return(0);
- }
-
- /* Z C H I N -- Get a character from the input file. */
-
- /* Returns -1 if EOF, 0 otherwise with character returned in argument */
-
- int
- zchin(n,c) int n, *c; {
- int a;
-
- #ifdef DEBUG
- if (chkfn(n) < 1) return(-1);
- #endif
-
- if (n == ZIFILE && subprocess_input) {
- if (--sub_count < 0)
- if (get_subprc_line()) return(-1);
- a = *sub_ptr++;
- } else {
- a = zminchar();
- }
- if (a == EOF) return(-1);
- *c = (unsigned char)a;
- return(0);
- }
-
- /* Z S I N L -- Read a line from a file. */
-
- /*
- Writes the line into the address provided by the caller.
- n is the Kermit "channel number".
- Writing terminates when newline is encountered, newline is not copied.
- Writing also terminates upon EOF or if length x is exhausted.
- Returns 0 on success, -1 on EOF or error.
- */
-
- int
- zsinl(n,s,x) int n, x; char *s; {
- int a, z = 0;
- int old;
-
- if (chkfn(n) < 1) { /* Make sure file is open */
- return(-1);
- }
- a = -1;
- while (x--) {
- old = a; /* Previous character */
- if (zchin(n,&a) < 0) /* Read a character from the file */
- return(-1); /* Signal EOF if problem */
- a = a & 0377;
- #ifdef NLCHAR
- if (a == (char) NLCHAR) break; /* Single-character line terminator */
- #else
- if (a == '\r') continue; /* CRLF line terminator */
- if (old == '\r') {
- if (a == '\n') break;
- else *s++ = '\r';
- }
- #endif /* NLCHAR */
- *s = a;
- s++;
- }
- *s = '\0';
- return(z);
- }
-
- /* Z I N F I L L -- Read a line from a file. */
-
- /*
- * (re)fill the buffered file input buffer with data. All file input
- * should go through this routine, usually by calling the zminchar()
- * macro (defined in ckcker.h).
- */
-
- int
- zinfill() {
- char cchar;
- int linelen;
-
- if (subprocess_input) {
- if (get_subprc_line()) return(-1);
-
- /*
- * The size problem should never happen. sub_buf of a size greater then
- * 1k is highly unlikely to be needed.
- */
-
- if (INBUFSIZE < SUB_BUF_SIZE) {
- fprintf(stderr,"zinfill: sub_buf too large for zinbuffer");
- exit();
- }
- zinptr = sub_buf;
- zincnt = sub_count;
- } else {
- if (ifile_bmode != 0) {
- rab_ifile.rab$l_rop = RAB$M_BIO; /* block mode I/O */
- #ifdef DYNAMIC
- rab_ifile.rab$l_ubf = zinbuffer;
- #else
- rab_ifile.rab$l_ubf = &zinbuffer;
- #endif
- rab_ifile.rab$w_usz = 512;
- rms_sts = sys$read(&rab_ifile);
- if (rms_sts == RMS$_EOF)
- return(-1); /* end of file */
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zinfill $read failed, status","",rms_sts);
- return(-1); /* fatal */
- }
- ifile_bcount++; /* say another block read */
- zincnt = 512;
- if (ifile_bcount == xabfhc_ifile.xab$l_ebk) {
- if (ifile_bmode == 1) /* BINARY but not LABELED */
- zincnt = xabfhc_ifile.xab$w_ffb;
- }
- zinptr = zinbuffer;
- zincnt--; /* one less char in buffer */
- return((int)(*zinptr++) & 0377); /* because we return the first */
- }
- if (fab_ifile.fab$b_rat & FAB$M_FTN) {
- #ifdef DYNAMIC
- rab_ifile.rab$l_ubf = zinbuffer+2;
- #else
- rab_ifile.rab$l_ubf = &zinbuffer+2;
- #endif
- rab_ifile.rab$w_usz = INBUFSIZE-4; /* space for carriage ctl */
- } else {
- #ifdef DYNAMIC
- rab_ifile.rab$l_ubf = zinbuffer;
- #else
- rab_ifile.rab$l_ubf = &zinbuffer;
- #endif
- rab_ifile.rab$w_usz = INBUFSIZE-2; /* space for possible CR/LF */
- }
- rab_ifile.rab$l_rop = 0; /* doing record I/O */
- rms_sts = sys$get(&rab_ifile);
- if (rms_sts == RMS$_EOF)
- return(-1); /* end of file */
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zinfill $get failed, status","",rms_sts);
- return(-1); /* fatal */
- }
-
- /*
- * Do assorted contortions with Fortran carriage control to make it formatted
- * ASCII instead, since many systems don't know about Fortran format in files.
- */
-
- if (fab_ifile.fab$b_rat & FAB$M_FTN) {
- linelen = rab_ifile.rab$w_rsz-1; /* sans control code */
- cchar = zinbuffer[2]; /* control code */
- switch (cchar) {
- case '\0': /* data<CR> */
- case '+':
- zinbuffer[linelen+3] = '\r';/* insert return */
- zinptr = zinbuffer+3;
- zincnt = linelen+1; /* count it */
- break;
- case '$': /* <LF>data<CR> */
- case ' ':
- zinbuffer[2] = '\n'; /* insert newline */
- zinbuffer[linelen+3] = '\r';/* insert return */
- zinptr = zinbuffer+2;
- zincnt = linelen+2; /* count 'em */
- break;
- case '0': /* <LF><CR><LF>data<CR> */
- zinbuffer[0] = '\n'; /* insert 1st newline */
- zinbuffer[1] = '\r'; /* insert 1st return */
- zinbuffer[2] = '\n'; /* insert 2nd newline */
- zinbuffer[linelen+3] = '\r';/* insert 2nd return */
- zinptr = zinbuffer;
- zincnt = linelen+4; /* count 'em */
- break;
- case '1': /* <FF>data<CR> */
- zinbuffer[2] = '\f'; /* insert formfeed */
- zinbuffer[linelen+3] = '\r';/* insert return */
- zinptr = zinbuffer+2;
- zincnt = linelen+2; /* count 'em */
- break;
- default: /* <LF>data<CR> */
- zinbuffer[2] = '\n'; /* insert newline */
- zinbuffer[linelen+3] = '\r';/* insert return */
- zinptr = zinbuffer+2;
- zincnt = linelen+2; /* count 'em */
- break;
- }
- } else {
- zincnt = rab_ifile.rab$w_rsz;
- zinptr = zinbuffer; /* reset pointer */
- }
-
- /*
- * Here we see if we need to insert CR/LF pairs at the record boundary. For
- * the moment, we will add them if the file has "carriage return carriage
- * control" when looked at by a DIRECTORY command. As of edit 036 we also do
- * this for "print file carriage control" files. I'm open to comments de-
- * scribing cases where this doesn't work...
- */
-
- if (fab_ifile.fab$b_rat & (FAB$M_CR | FAB$M_PRN)) {
- zinbuffer[zincnt] = '\r';
- zinbuffer[zincnt + 1] = '\n';
- zincnt += 2;
- }
- }
- zincnt--; /* one less char in buffer */
- return((int)(*zinptr++) & 0377); /* because we return the first */
- }
-
-
- /* Z S O U T -- Write a string to the given file, buffered. */
-
- int
- zsout(n,s) int n; char *s; {
- #ifdef DEBUG
- if (chkfn(n) < 1) return(-1);
- #endif
- fputs(s, fp[n]); /* Don't use fprintf here MM */
- return(0);
- }
-
-
- /* Z S O U T L -- Write string to file, with line terminator, buffered. */
-
- int
- zsoutl(n,s) int n; char *s; {
- #ifdef DEBUG
- if (chkfn(n) < 1) return(-1);
- #endif
- fputs(s, fp[n]); /* Don't use fprintf MM */
- putc('\n', fp[n]);
- return(0);
- }
-
-
- /* Z S O U T X -- Write x characters to file, unbuffered. */
-
- int
- zsoutx(n,s,x) int n, x; char *s; {
- #ifdef DEBUG
- if (chkfn(n) < 1) return(-1);
- #endif
- return(write(fileno(fp[n]),s,x));
- }
-
-
- /* Z C H O U T -- Add a character to the given file. */
-
- int
- #ifdef CK_ANSIC
- zchout(register int n, char c)
- #else
- zchout(n,c) register int n; char c;
- #endif /* CK_ANSIC */
- /* zchout */ {
- #ifdef DEBUG
- if (chkfn(n) < 1) return(-1);
- #endif
- if (n == ZSFILE) {
- return(write(fileno(fp[n]),&c,1)); /* Use unbuffered for session log */
- } else {
- if (putc(c,fp[n]) == EOF) /* If true, maybe there was an error */
- return(ferror(fp[n]) ? -1 : 0); /* Check to make sure */
- else /* Otherwise... */
- return(0); /* There was no error. */
- }
- }
-
- /* Z O U T D U M P -- dump buffered output characters to file. */
-
- /* Buffered file output, buffer dump */
-
- /*
- * No, this isn't an entry in the 199x Obfuscated C programming contest, nor
- * did we get it at an all-night convenience store. VMS requires that stream
- * format files be written as records, so we have to do _lots_ of contortion
- * to make sure we write whole lines as records. Not pretty.
- */
-
- int
- zoutdump() {
- int ocnt;
- int wrote_one_line = 0;
- CHAR *optr, *srcptr, *endptr;
- char csave;
-
- debug(F101," zoutdump zoutcnt","",zoutcnt);
- debug(F101," zoutdump ofile_bmode","",ofile_bmode);
-
- /*
- * Well, this could be to the console. If it is, chop it into itty-bitty parts
- * (the VMS CRTL can't handle a %s spec bigger than 512 bytes) and print it.
- */
-
- if (cflag == 1) { /* If we're dumping to console */
- endptr = zoutbuffer + zoutcnt;
- for (optr = zoutbuffer; optr < endptr; optr += 511) {
- if (optr+511 < endptr) { /* More than 511, break up */
- csave = *(optr+511);
- *(optr+511) = '\0';
- printf("%s", optr);
- *(optr+511) = csave;
- }
- else {
- *endptr = '\0'; /* Make sure null-terminated */
- printf("%s", optr);
- }
- }
- zoutcnt = 0;
- zoutptr = zoutbuffer;
- return(0);
- }
-
- /*
- * Do we need to processed TYPE LABELED contortions?
- */
-
- if (ofile_bmode == XYFT_L) { /* Is it labeled? */
- if (ofile_lblproc == 0) { /* I've never gone this way before? */
- rms_sts = do_label_recv(); /* Beyond revolving rainbow door... */
- if (rms_sts == -1)
- return(-1); /* Got a hard error in label proc. */
- if (rms_sts == 1 && ofile_dump != 1)
- return(0); /* Exit so we can fill up the buffer */
- }
- }
-
- /*
- * Well, we could be lucky...
- */
-
- if (zoutcnt == 0)
- return(0);
-
- /*
- * Oh well. See if doing binary - that's easy...
- */
-
- if (ofile_bmode) {
- if (zoutcnt == OBUFSIZE) {
- #ifdef DYNAMIC
- rab_ofile.rab$l_rbf = zoutbuffer;
- #else
- rab_ofile.rab$l_rbf = &zoutbuffer;
- #endif /* DYNAMIC */
- rab_ofile.rab$w_rsz = OBUFSIZE;
- if (ofile_ffb != -1 && ofile_dump == 1) {
- /*
- * Only do this when doing _last_ file segment.
- */
- xabfhc_ofile.xab$w_ffb = ofile_ffb;
- if (ofile_ffb)
- rab_ofile.rab$w_rsz -= (512 - ofile_ffb);
- debug(F101," zoutdump ofile_ffb","",(int)ofile_ffb);
- debug(F101," zoutdump rab$w_rsz","",rab_ofile.rab$w_rsz);
- }
- rms_sts = sys$write(&rab_ofile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zoutdump $write failed, status","",rms_sts);
- return(-1);
- }
- } else {
- #ifdef DYNAMIC
- rab_ofile.rab$l_rbf = zoutbuffer;
- #else
- rab_ofile.rab$l_rbf = &zoutbuffer;
- #endif
- rab_ofile.rab$w_rsz = zoutcnt;
- xabfhc_ofile.xab$w_ffb = (zoutcnt & 511)+1;
- if (ofile_ffb != -1) {
- xabfhc_ofile.xab$w_ffb = ofile_ffb;
- if (ofile_ffb)
- rab_ofile.rab$w_rsz -= (512 - ofile_ffb);
- debug(F101," zoutdump ofile_ffb","",(int)ofile_ffb);
- debug(F101," zoutdump rab$w_rsz","",rab_ofile.rab$w_rsz);
- }
- rms_sts = sys$write(&rab_ofile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zoutdump $write failed, status","",rms_sts);
- return(-1);
- }
- }
- debug(F100," zoutdump RMS operations completed ok","",0);
- zoutcnt = 0;
- zoutptr = zoutbuffer;
- return(0);
- }
-
- /*
- * Must be ASCII. This is harder, and weirder... It's actually easier than
- * it looks, but there's (unfortunately) no really easy way to _implement_
- * it. (sigh, whimper, groan)
- */
-
- srcptr = zoutbuffer; /* Points to first line in buffer */
- endptr = zoutbuffer + zoutcnt; /* Points to location after last char */
- zoutdump_ascii:
- /* Scan through buffer until we find a CR or we run out of chars */
- for (optr = srcptr; optr < endptr; optr++) if (*optr == CR) break;
-
- /* If there are at least 2 chars left in the buffer when we stop */
- /* scanning, then it is assumed the above loop terminated because */
- /* it found the CR and that both the CR and LF are present in the */
- /* buffer (situation normal. */
- /* If there are not 2 chars left in the buffer, we have one of two */
- /* cases which we treat identically: */
- /* 1) If there are 0 chars left in the buffer, then the line's */
- /* terminating CR LF are yet to come. So... we copy the data */
- /* to the front of the buffer and exit (next time it should be */
- /* there.) */
- /* 2) If there is one char left in the buffer, we have the case of*/
- /* a line with the CR but no LF present. So... do the same */
- /* because the LF will be coming next time. */
- if (optr+2 > endptr) { /* drat! ran off the end */
- if (ofile_dump && (srcptr == endptr)) {
- /* If the beginning and end ptrs are the same, then there the */
- /* is empty. Good news, 'cause we're clsoing up. */
- zoutcnt = 0; /* No looping, please. */
- zoutptr = zoutbuffer;
- }
- else if (ofile_dump) { /* but it's cool, we're closing up */
- /* Oops, we've got a line with no LF and maybe no CR. Well */
- /* write it out and exit abnormally. */
- rab_ofile.rab$l_rbf = srcptr;
- rab_ofile.rab$w_rsz = optr-srcptr;
- rms_sts = sys$put(&rab_ofile);
- zoutcnt = 0;
- zoutptr = zoutbuffer;
- if (rms_sts != RMS$_NORMAL) {
- debug(F101, " zoutdump $put failed, status","",rms_sts);
- return(-1);
- }
- } else if (wrote_one_line) { /* it's still cool, we did one... */
- zoutcnt = optr - srcptr; /* number of chars left */
- if (optr < endptr) zoutcnt++; /*[jah083] including CR if present */
- if (zoutcnt) memmove(zoutbuffer, srcptr, zoutcnt);
- /* Move'em to front of buffer*/
- zoutptr = zoutbuffer+zoutcnt;
- } else { /* WRONG!!! */
- /* We've got a buffer full of chars with no LF (it may or may */
- /* not have a terminating CR. In either case its just plain too*/
- /* long. I suppose we could check here for the optr+1 == endptr*/
- /* which indicates that there was a CR but no LF so we could */
- /* issue a "line barely too long", but, is it useful? */
- debug(F100, "zoutdump: line too long","",0);
- zoutcnt = 0; /* No looping, please. */
- zoutptr = zoutbuffer;
- return(-1);
- }
- debug(F101, " zoutdump exiting, zoutcnt","",zoutcnt);
- return(0);
- }
-
- /* We now have a line that we can write, so... */
-
- rab_ofile.rab$l_rbf = srcptr;
- rab_ofile.rab$w_rsz = optr-srcptr;
- rms_sts = sys$put(&rab_ofile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101, " zoutdump $put failed, status","",rms_sts);
- return(-1);
- }
- srcptr = optr + 2; /* Account for CR, LF */
- wrote_one_line = 1;
- goto zoutdump_ascii;
- }
-
- /* C H K F N -- Internal function to verify file number is ok. */
-
- /*
- Returns:
- -1: File number n is out of range
- 0: n is in range, but file is not open
- 1: n in range and file is open
- */
-
- int
- chkfn(n) int n; {
- switch (n) {
- case ZCTERM:
- case ZSTDIO:
- case ZIFILE:
- case ZOFILE:
- case ZDFILE:
- case ZTFILE:
- case ZPFILE:
- case ZSFILE:
- break;
- case ZSYSFN: /* System functions */
- return(0);
- case ZRFILE: /* READ and WRITE files */
- case ZWFILE:
- case ZMFILE:
- break;
- default:
- debug(F101,"chkfn: file number out of range","",n);
- fprintf(stderr,"?File number out of range - %d\n",n);
- return(-1);
- }
- return( (fp[n] == NULL) ? 0 : 1 );
- }
-
- /* Z C H K I -- Check if input file exists and is readable. */
-
- /*
- Returns:
- >= 0 if the file can be read (returns the size).
- -1 if file doesn't exist or can't be accessed,
- -2 if file exists but is not readable (e.g. a directory file).
- -3 if file exists but protected against read access.
- */
-
- long
- zchki(name) char *name; {
- struct stat buf;
- int x; long y;
-
- /* This is _really_ bad. But there's a fundamental assumption in the upper
- * levels that one can call zchki() without any context to validate file-
- * names, directory names, etc. which would be painful (to the other imple-
- * mentations) to change. So, if we get an argument which ends in ':', '>',
- * or ']', we'll return an immediate OK with a size of 0. Bad directory
- * names will be caught in zchdir anyway. This has the nice side-effect that
- * saying (for example) GET dir-spec will implicitly get all files in that
- * directory. Not bad for a total kludge, huh?
- */
- x = strlen(name);
- if (name[x-1] == ':')
- return(0);
- if (name[x-1] == ']')
- return(0);
- if (name[x-1] == '>')
- return(0);
-
- fab_ifile = cc$rms_fab;
- fab_ifile.fab$b_fac = FAB$M_BIO;
- fab_ifile.fab$l_fna = name;
- fab_ifile.fab$b_fns = strlen(name);
- fab_ifile.fab$l_xab = (char *)&xabfhc_ifile;
- xabfhc_ifile = cc$rms_xabfhc;
- rms_sts = sys$open(&fab_ifile);
- if (rms_sts == RMS$_PRV) /* No privs */
- return(-3);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zchki $open failed, status","",rms_sts);
- return(-1);
- }
- iflen = ((xabfhc_ifile.xab$l_ebk-1)*512)+xabfhc_ifile.xab$w_ffb;
-
- rms_sts = sys$close(&fab_ifile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zchki $close failed, status","",rms_sts);
- return(-1);
- }
- strcpy(nambuf,name); /* preserve name */
- debug(F111," zchki access ok:",name,(int) iflen); /* Yes */
- return( (iflen > -1) ? iflen : 0 );
- }
-
- /* Z C H K O -- Check if output file can be created. */
-
- /*
- Returns -1 if write permission for the file would be denied, 0 otherwise.
- */
- int
- zchko(name) char *name; {
- return(0); /* Always creates new version */
- }
-
- /* Z C H K S P A -- Check if there is enough space to store the file. */
-
- /*
- Call with file specification f, size n in bytes.
- Returns -1 on error, 0 if not enough space, 1 if enough space.
- */
-
- int
- zchkspa(f,n) char *f; long n; {
-
- /*
- * This is complicated. The user could have specified an explicit path when
- * sending the file, or could have done a CWD, or could be using the default
- * directory. If not the latter, the path may not even be a disk device, as
- * CWD LPA0: is perfect legal for uploading to the lineprinter. After that,
- * if it's a disk, we should check the user's quota. However, the user may
- * have SYSPRV, EXQUOTA, BYPASS, or maybe even GRPPRV, and it would be hard
- * to properly check for all these cases. So, if the file will fit on the
- * disk, we'll accept it.
- */
-
- char *zgtdir();
-
- struct itmlstdef {
- short int buflen;
- short int itmcod;
- char *bufaddr;
- long int *retlen;
- };
-
- static char device[64];
-
- struct dsc$descriptor_s
- dev_desc = {sizeof(device), DSC$K_DTYPE_T, DSC$K_CLASS_S,
- (char *)&device};
- unsigned long freeblocks, freelength, devclass, classlength, fileblocks;
-
- struct itmlstdef itmlst[] =
- {4,DVI$_FREEBLOCKS,0,0,4,DVI$_DEVCLASS,0,0,0,0,0,0};
-
- int rms_sts;
-
- /* First, figure out the device we're interested in */
-
- strcpy(device, zgtdir()); /* Handles default or CWD */
-
- if (strchr(f, ':')) /* If user specified path */
- strncpy(device, f, 63);
-
- debug(F110," zchkspa target device is ",device,0);
-
- /* Next, ask for free block count and device type (disk vs. non-disk) */
-
- itmlst[0].bufaddr = (char *)&freeblocks;
- itmlst[0].retlen = &freelength;
- itmlst[1].bufaddr = (char *)&devclass;
- itmlst[1].retlen = &classlength;
-
- rms_sts = sys$getdviw(0,0,&dev_desc,&itmlst,0,0,0,0);
-
- debug(F101," zchkspa $getdvi returned rms_sts","",rms_sts);
-
- if (devclass != DC$_DISK)
- return(1); /* assume space if not disk */
-
- if (rms_sts != SS$_NORMAL)
- return(1); /* assume free space if err */
-
- debug(F101," zchkspa $getdvi returned freeblocks","",freeblocks);
-
- /* Pad file size if it's a text file */
-
- if (ofile_bmode == XYFT_T)
- n += (n/40) * 3;
-
- fileblocks = n / 512 + 1; /* compute file size in blks */
- /* we may want some fuzz */
- if (fileblocks >= freeblocks)
- return(0); /* Won't fit */
- else
- return(1); /* Will fit */
- }
-
- /* Z D E L E T -- Delete the named file. */
-
- int
- zdelet(name) char *name; {
- return(delete(name));
- }
-
- /* Z R T O L -- Convert remote filename into local form. */
-
- VOID
- zrtol(name,name2) char *name, *name2; {
- int count = 9, vflag = 0;
- char *cp, c;
- static char *spcl_set = "_-$[]<>:.\";";
-
- for (cp=name2; c = *name; name++) {
- if (islower(c)) c = toupper(c);
- if (!isalnum(c) &&
- !strchr(spcl_set,c)) c = 'X';
- *cp++ = c;
- }
- *cp = '\0'; /* End of name */
- debug(F110," zrtol: ",name2,0);
- }
-
- /* Z L T O R -- Convert filename from local format to common form. */
-
- VOID
- zltor(name,name2) char *name, *name2; {
- char *cp, *pp;
-
- /*
- * Copy name to output string
- */
-
- strcpy(name2,name);
-
- /*
- * Parse the filename and type, with the default filename of "X"
- */
-
- parse_fname(name2, 100, "X", PARSE_NAME|PARSE_TYPE);
- debug(F110," zltor: ",name2,0);
- }
-
- /* Z C H D I R -- Change directory. */
-
- int
- zchdir(dirnam) char *dirnam; {
-
- char *zgtdir();
- char dir_buff[NAM$C_MAXRSS];
- int status;
-
- if (*dirnam == '\0')
- strcpy(dirnam,getenv("HOME")); /* default to current dir */
-
- status = chdir(dirnam); /* change first in parent proc */
- return(status == 0);
- }
-
- /* Z H O M E -- Return pointer to user's home directory. */
-
- char *
- zhome() {
- return(getenv("HOME"));
- }
-
- /* Z G T D I R -- Return pointer to user's current directory. */
-
- char *
- zgtdir() {
- #ifdef VMS_V40
- #define OLD_VMS
- #endif
- #ifdef VMS_V42
- #define OLD_VMS
- #endif
- #ifdef VMS_V44
- #define OLD_VMS
- #endif
- #ifdef VAXC023
- #define OLD_VMS
- #endif
- #ifdef VAXC024
- #define OLD_VMS
- #endif
-
- #ifdef OLD_VMS
- static char *gtdir_buf = 0;
- static char sysdisk[] = "SYS$DISK";
- char tmp_buf[NAM$C_MAXRSS+1];
- struct dsc$descriptor_s
- tmp_buf_dsc = {sizeof(tmp_buf),DSC$K_DTYPE_T,DSC$K_CLASS_S,&tmp_buf},
- sysdisk_dsc = {sizeof(sysdisk)-1,DSC$K_DTYPE_T,DSC$K_CLASS_S,&sysdisk};
- unsigned short int buf_len;
-
- /*
- * Allocate buffer dynamically, first time through. This makes the image
- * smaller.
- */
-
- if (!gtdir_buf) gtdir_buf = malloc(NAM$C_MAXRSS+1);
-
- /*
- * Translate device name.
- */
-
- LIB$SYS_TRNLOG( &sysdisk_dsc,
- &buf_len,
- &tmp_buf_dsc,
- 0,
- 0,
- 0);
- tmp_buf[buf_len] = '\0';
- strcpy(gtdir_buf,tmp_buf);
-
- /*
- * Get directory name.
- */
-
- sys$setddir( 0, /* New dir addr */
- &buf_len, /* length addr */
- &tmp_buf_dsc);
- tmp_buf[buf_len] = '\0';
- strcat(gtdir_buf,tmp_buf);
-
- return(gtdir_buf); /* Can't seem to make LINK find getcwd()... */
- /* (wbader: removed &) */
- #else
- char *getcwd();
- char *buf;
-
- buf = cwdbuf;
- return(getcwd(buf,100));
- #endif
- }
-
- /* Z X C M D -- Run a system command so its output can be read as a file. */
-
- int
- zxcmd(filnum, comand) int filnum; char *comand; {
- char mbxnam[21], inpchan[6] = "NLA0:";
- unsigned long sts, pid;
- int one=1;
-
- struct dsc$descriptor_s
- mbx_desc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0},
- cmd_line = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0},
- inp_desc = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
-
- struct itmlstdef {
- short int buflen;
- short int itmcod;
- char *bufaddr;
- long int *retlen;
- };
-
- struct itmlstdef itmlst[] = {
- 4, JPI$_PID, (char *)&pid, 0,
- 0, 0, 0, 0
- };
-
- debug(F101,"zxcmd filnum", "", filnum);
- if (filnum != ZIFILE && filnum != ZRFILE)
- return(0);
-
- sts = sys$getjpiw(0, 0, 0, &itmlst, 0, 0, 0);
-
- debug(F101,"zxcmd sys$getjpiw status", "", sts);
- if (sts != SS$_NORMAL)
- return(0);
-
- sprintf(mbxnam,"KERMIT$MBX_%08X", pid);
- debug(F110,"zxcmd mailbox logical", mbxnam, 0);
-
- mbx_desc.dsc$w_length = strlen(mbxnam);
- mbx_desc.dsc$a_pointer = mbxnam;
-
- sts = sys$crembx(0, &mbx_chan, SUB_BUF_SIZE, 0, 0, 0, &mbx_desc, 0);
-
- debug(F101,"zxcmd sys$crembx status", "", sts);
- if (sts != SS$_NORMAL)
- return(0);
-
- debug(F101,"zxcmd sys$crembx mbx_chan", "", mbx_chan);
-
- strcat(mbxnam, ":");
- mbx_desc.dsc$w_length++;
-
- cmd_line.dsc$w_length = strlen(comand);
- cmd_line.dsc$a_pointer = comand;
-
- inp_desc.dsc$w_length = strlen(inpchan);
- inp_desc.dsc$a_pointer = inpchan;
-
- sts = lib$spawn(&cmd_line, &inp_desc, &mbx_desc, &one, 0, &sub_pid,
- 0, 0, 0, &mbx_chan);
-
- debug(F101,"zxcmd lib$spawn status", "", sts);
- if (sts != SS$_NORMAL)
- return(0);
-
- subprocess_input = 1;
- sub_count = 0;
- fp[filnum] = fopen("NLA0:","r"); /* It wants a fp, give it one */
- debug(F101,"zxcmd fp[filnum]", "", fp[filnum]);
- fp[ZSYSFN] = fp[filnum]; /* Set ZSYSFN too, so we remember */
- return(1);
- }
-
- /* Z C L O S F - close the suprocess output file. */
-
- int
- zclosf(filnum) int filnum; {
- unsigned long sts;
-
- if (subprocess_input != 0) {
- sts = sys$delprc(&sub_pid, 0);
-
- debug(F101,"zclosf sys$delprc status", "", sts);
-
- sts = sys$delmbx(mbx_chan);
-
- debug(F101,"zclosf sys$delmbx status", "", sts);
-
- sts = sys$dassgn(mbx_chan);
-
- debug(F101,"zclosf sys$dassgn status", "", sts);
-
- sub_ptr = sub_buf; /* flush remaining data */
- sub_count = 1;
- *sub_buf = '\0';
- zincnt = 0;
-
- fclose(fp[filnum]); /* Close the place-holders */
- fp[filnum] = fp[ZSYSFN] = NULL;
- }
- subprocess_input = 0; /* Say we're done */
- return(1);
- }
-
- /* Z X P A N D -- Expand a wildcard string into an array of strings. */
-
- /*
- Returns the number of files that match fn1, with data structures set up
- so that first file (if any) will be returned by the next znext() call.
- */
- int
- zxpand(fn) char *fn; {
- if (strlen(fn) == 0) /* Nothing asked for, */
- return(0); /* nothing returned. */
- fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */
- if (fcount > 0) {
- mtchptr = mtchs; /* Save pointer for next. */
- debug(F111," zxpand",mtchs[0],fcount);
- }
- return(fcount);
- }
-
- /* Z N E X T -- Get name of next file from list created by zxpand(). */
-
- /*
- Returns >0 if there's another file, with its name copied into the arg string,
- or 0 if no more files in list.
- */
- int
- znext(fn) char *fn; {
-
- if (fcount-- > 0) strcpy(fn,*mtchptr++);
- else *fn = '\0';
- debug(F111," znext",fn,fcount+1);
- return(fcount+1);
- }
-
- /* Z N E W N -- Make a new name for the given file. */
-
- VOID
- znewn(fn,s) char *fn, **s; {
- static char buf[NAM$C_MAXRSS];
-
- strcpy(buf, fn); /* Version numbers are handled by OS */
- *s = buf;
- }
-
- /*
- * fgen:
- * This is the actual name generator. It is passed a string,
- * possibly containing wildcards, and an array of character pointers.
- * It finds all the matching filenames and stores them into the array.
- * The returned strings are allocated from a static buffer local to
- * this module (so the caller doesn't have to worry about deallocating
- * them); this means that successive calls to fgen will wipe out
- * the results of previous calls. This isn't a problem here
- * because we process one wildcard string at a time.
- *
- * Input: a wildcard string, an array to write names to, the
- * length of the array.
- * Returns: the number of matches. The array is filled with filenames
- * that matched the pattern. If there wasn't enough room in the
- * array, -1 is returned.
- */
- int
- fgen(pat,resarry,len) char *pat,*resarry[]; int len; {
- struct dsc$descriptor_s
- file_spec = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0},
- result = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0},
- deflt = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
- unsigned long context = 0, status;
- int count = 0;
- char *def_str = "*.*";
-
- file_spec.dsc$w_length = strlen(pat);
- file_spec.dsc$a_pointer = pat;
-
- deflt.dsc$w_length = sizeof(def_str)-1;
- deflt.dsc$a_pointer = def_str;
-
- while (count < len
- && (status = LIB$FIND_FILE(&file_spec, &result, &context, &deflt))
- == RMS$_NORMAL) {
- resarry[count] = malloc(result.dsc$w_length + 1);
- strncpy(resarry[count], result.dsc$a_pointer, result.dsc$w_length);
- resarry[count][result.dsc$w_length] = '\0';
- count++;
- }
- #ifdef DVI$_ALT_HOST_TYPE
- LIB$FIND_FILE_END(&context); /* Only on V4 and later */
- #endif
- LIB$SFREE1_DD(&result);
- if (status == RMS$_FNF) return((count <= len) ? 0 : -1);
- if (status == RMS$_NMF) return(count);
- /* Bernd Onasch says that VMS sometimes returns RMS$_NORMAL here, so... */
- if (status == RMS$_NORMAL) return(count);
- /* Some other status. Return 0. */
- /* Improve this later based on results from following debug stmt. */
- debug(F101,"fgen unexpected failure status","",status);
- return(0);
- }
-
- /* Z R E N A M E -- Rename a file. */
-
- /* Call with old and new names */
- /* Returns 0 on success, -1 on failure. */
- int
- zrename(old,new) char *old, *new; {
- int sts;
-
- sts = rename(old,new);
-
- return((sts ? -1 : 0));
- }
-
- /* Z S T I M E -- Set or compare a file's creation date/time. */
-
- /*
- * Note: There's an additional value for parameter X on VAX/VMS systems. As
- * it's horribly painful to change a file's creation date after-the-fact we
- * call zstime with an argument of 2 to pre-set the date when creating the
- * file. An argument of 0 (which the main-line code thinks sets the date of
- * the output file) returns success but does nothing. Note that an invalid
- * or missing attribute packet will cause $bintim to return an error, which
- * causes the routine to exit. Since we pre-set the binary time to zero, we
- * will create the file "now", or say the incoming file is newer, whichever
- * is appropriate.
- */
- int
- zstime(f,yy,x) char *f; struct zattr *yy; int x; {
- int rms_sts;
- static char mth[13][4] = { "JAN","FEB","MAR","APR",
- "MAY","JUN","JUL","AUG",
- "SEP","OCT","NOV","DEC",
- ""};
- static char cdate[23]; /* Creation date yyyymmdd hh:mm:ss.00 */
- static char mnum[2];
- struct dsc$descriptor_s
- bintim_desc = {sizeof(cdate), DSC$K_DTYPE_T, DSC$K_CLASS_S,
- (char *)&cdate};
- unsigned long file_date[2], attr_date[2];
-
- /* First, make a system quadword date from what we got passed */
-
- char *dptr = yy->date.val;
- if (!dptr) return(-1);
- strcpy(cdate,"dd-mmm-yyyy 00:00:00.00");
- attr_date[0]=0; /* clear time in case of err */
- attr_date[1]=0;
- strncpy(cdate+7, dptr, 4); /* yyyy */
- dptr += 4;
- strncpy(mnum, dptr, 2);
- strncpy(cdate+3, mth[atoi(mnum)-1], 3); /* mm */
- dptr += 2;
- strncpy(cdate, dptr, 2); /* dd */
- dptr += 3;
- strncpy(cdate+12, dptr, 8); /* hhmmss */
- cdate[23] = '\0'; /* terminate */
- rms_sts = sys$bintim(&bintim_desc, &attr_date);
- if (rms_sts != SS$_NORMAL) {
- debug(F101," zstime - $bintim returns","",rms_sts);
- return(-1);
- }
- debug(F110," zstime built",cdate,0);
- sprintf(cdate, "%08X%08X", attr_date[1], attr_date[0]);
- debug(F110," $bintim attr_date", cdate, 0);
-
- if (x == 1) {
- fab_ifile = cc$rms_fab;
- fab_ifile.fab$b_fac = FAB$M_BIO | FAB$M_GET;
- fab_ifile.fab$l_fna = f;
- fab_ifile.fab$b_fns = strlen(f);
- fab_ifile.fab$l_xab = (char *)&xabdat_ifile;
- rab_ifile = cc$rms_rab;
- rab_ifile.rab$l_fab = &fab_ifile;
- xabdat_ifile = cc$rms_xabdat;
- rms_sts = sys$open(&fab_ifile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zstime $open failed, status","",rms_sts);
- return(-1);
- }
- memcpy(file_date, &xabdat_ifile.xab$q_cdt, 8);
- sprintf(cdate, "%08x%08x", file_date[1], file_date[0]);
- debug(F110," $bintim file_date", cdate, 0);
- rms_sts = sys$close(&fab_ifile);
- if (rms_sts != RMS$_NORMAL) {
- debug(F101," zstime $close failed, status","",rms_sts);
- return(-1);
- }
- if (attr_date[1] < file_date[1]) {
- debug(F100," zstime incoming file is older","",0);
- return(1);
- }
- if (attr_date[1] == file_date[1]) {
- if (attr_date[0] <= file_date[0]) {
- debug(F100," zstime incoming file is older, not by much","",0);
- return(1);
- }
- debug(F100," zstime incoming file is newer","",0);
- return(0);
- }
- }
-
- if (x == 0) {
- return(0); /* say we did it (see header) */
- }
-
- if (x == 2) {
- memcpy(&xabdat_ofile.xab$q_cdt, attr_date, 8);
- return(0); /* Set date in output file */
- }
-
- return(-1);
- }
-
- /* Z K E R M I N I -- Find initialization file. */
- /*
- Places name of init file in buffer pointed to by s.
- If no init file found, the device name of the null device is used.
- returns 0 always.
- */
- int
- zkermini(s, s_len, def) char *s; int s_len; char *def; {
- FILE fd;
- struct dsc$descriptor_s
- dsc_in = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0},
- dsc_out = {0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0},
- dsc_def = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
- int max_len;
- long unsigned int rms_s;
- unsigned long find_file_context = 0;
-
- struct TRNLIST {
- char *name; /* ASCII file or logical name */
- unsigned char flag; /* Zero to use default filename */
- } *p;
-
- static struct TRNLIST slist[] = {
- {"", 0}, /* Dummy first entry points to file */
- {"ckermit_ini:", 0}, /* CKERMIT_INI: points to directory */
- {"ckermit_init", 1}, /* CKERMIT_INIT points to file */
- {"sys$login:", 0}, /* CKERMIT.INI in login directory */
- {"", 0}
- };
- p = slist; /* Point to list */
- if (rcflag) { /* Name given on command line? */
- slist[0].name = def; /* Yes, stuff its name into slist */
- slist[1].name = "";
- } else { /* No, */
- *p++; /* skip past dummy entry. */
- }
- while(*(p->name)) { /* Search the list top to bottom */
-
- dsc_in.dsc$w_length = strlen(p->name); /* Length of work area */
- dsc_in.dsc$a_pointer = p->name; /* Address of string */
-
- if (!(p->flag)) {
- dsc_def.dsc$w_length = strlen(def); /* Length of work area */
- dsc_def.dsc$a_pointer = def; /* Address of string */
- } else {
- dsc_def.dsc$w_length = 0; /* Length of work area */
- dsc_def.dsc$a_pointer = 0; /* Address of string */
- }
- rms_s = LIB$FIND_FILE(
- &dsc_in, /* File spec */
- &dsc_out, /* Result file spec */
- &find_file_context, /* Context */
- &dsc_def, /* Default file spec */
- 0, /* Related spec */
- 0, /* STV error */
- 0); /* Flags */
-
- if (rms_s == RMS$_NORMAL) {
- max_len = ((unsigned short int) dsc_out.dsc$w_length < s_len ?
- (unsigned short int) dsc_out.dsc$w_length : 0);
- if (!max_len)
- fprintf(stderr,
- "%%ZKERMINI out string not long enough, ignoring .ini file\n");
- else
- strncpy(s,dsc_out.dsc$a_pointer,max_len);
- LIB$FIND_FILE_END(&find_file_context);
- LIB$SFREE1_DD(&dsc_out); /* Return dyno memory */
- return(0);
- }
- p++;
- LIB$FIND_FILE_END(&find_file_context);
- }
- /*
- * No initialization file found. We can't return the null string because the
- * runtime library will successfully open it if the file ".;" exists in the
- * user's directory. Instead we return the name of the null device.
- */
- strcpy(s, "NLA0:"); /* Return null init file */
- LIB$SFREE1_DD(&dsc_out);
- return(0);
- }
-
- static int
- parse_fname(cp, cp_len, defnam, flag)
- char *cp; /* Pointer to file spec to parse */
- int cp_len; /* Length of cp field */
- char *defnam; /* Default file spec */
- int flag; /* Flag word PARSE_xxx */
- {
- struct FAB fab;
- struct NAM nam;
- char expanded_name[NAM$C_MAXRSS];
- int long rms_status;
- int cur_len = 0;
-
- fab = cc$rms_fab;
- fab.fab$l_nam = &nam;
- fab.fab$l_fna = cp;
- fab.fab$b_fns = strlen(cp);
- if (defnam) {
- fab.fab$b_dns = strlen(defnam);
- fab.fab$l_dna = defnam;
- } else
- fab.fab$l_dna = 0;
-
- nam = cc$rms_nam;
- nam.nam$l_esa = (char *)&expanded_name;
- nam.nam$b_ess = sizeof(expanded_name);
-
- if (!CHECK_ERR("%%CKERMIT-W-PARSE, ",
- sys$parse(&fab)))
- return(-1);
-
- *cp = '\0'; /* Make a zero length string */
- if ((PARSE_NODE & flag) && nam.nam$b_node &&
- cur_len+nam.nam$b_node < cp_len) {
- cur_len += nam.nam$b_node;
- strncat(cp, nam.nam$l_node, (int)nam.nam$b_node);
- }
- if ((PARSE_DEVICE & flag) && nam.nam$b_dev &&
- cur_len+nam.nam$b_dev < cp_len) {
- cur_len += nam.nam$b_dev;
- strncat(cp, nam.nam$l_dev, (int)nam.nam$b_dev);
- }
- if ((PARSE_DIRECTORY & flag) && nam.nam$b_dir &&
- cur_len+nam.nam$b_dir < cp_len) {
- cur_len += nam.nam$b_dir;
- strncat(cp, nam.nam$l_dir, (int)nam.nam$b_dir);
- }
- if ((PARSE_NAME & flag) && nam.nam$b_name &&
- cur_len+nam.nam$b_name < cp_len) {
- cur_len += nam.nam$b_name;
- strncat(cp, nam.nam$l_name, (int)nam.nam$b_name);
- }
- if ((PARSE_TYPE & flag) && nam.nam$b_type &&
- cur_len+nam.nam$b_type < cp_len) {
- cur_len += nam.nam$b_type;
- strncat(cp, nam.nam$l_type, (int)nam.nam$b_type);
- }
- if ((PARSE_VERSION & flag) && nam.nam$b_ver &&
- cur_len+nam.nam$b_ver < cp_len) {
- cur_len += nam.nam$b_ver;
- strncat(cp, nam.nam$l_ver, (int)nam.nam$b_ver);
- }
- return(cur_len);
- }
-
- /* Z S A T T R -- Fill in a Kermit attribute structure for current file. */
-
- /*
- Fills in a Kermit file attribute structure for the file which is to be sent.
- Returns 0 on success with the structure filled in, or -1 on failure.
- If any string member is null, then it should be ignored.
- If any numeric member is -1, then it should be ignored.
- */
- int
- zsattr(xx) struct zattr *xx; {
- long k;
- int x;
- static char mth[13][4] = { "JAN","FEB","MAR","APR",
- "MAY","JUN","JUL","AUG",
- "SEP","OCT","NOV","DEC",
- ""};
- static char recfm[15]; /* record format */
- static char cdate[20]; /* Creation date [yy]yymmdd[hh:mm[:ss]]*/
- static char creater_id[31]; /* Creator ID string */
- static unsigned char genprot; /* Generic protection */
- static unsigned short lclprot; /* Local protection */
- static long sysparam_size=0; /* Length of system paramater buffer */
- static char *sysparam_adr=0; /* Address of system paramater buffer */
- char type; /* File type */
- short int asctim_retlen;
- char asctim_buf[24]; /* Work buffer for ASCTIM() */
- struct dsc$descriptor_s
- asctim_dsc = {sizeof(asctim_buf),DSC$K_DTYPE_T,DSC$K_CLASS_S,
- (char *)&asctim_buf};
- static long int i;
- static unsigned short id_len;
- static struct dsc$descriptor_s id_str =
- {31,DSC$K_DTYPE_T,DSC$K_CLASS_S,creater_id};
-
- /*
- * Zero out strings
- */
-
- type = 0;
- recfm[0] = '\0';
- cdate[0] = '\0';
- creater_id[0] = '\0';
- id_len = 0;
- genprot = 0; /* Blank protection by default */
- lclprot = 0;
-
- /*
- * See if we are sending "attributes" from a REMOTE command response
- */
-
- if (*nambuf == '\0') {
- xx->lengthk = 1; /* Number of 1K blocks rounded up */
- xx->type.len = 0; /* File type can't be filled in here */
- xx->type.val = "";
- xx->date.len = strlen(cdate); /* File creation date */
- xx->date.val = (char *)&cdate;
- xx->creator.len = strlen(creater_id); /* File creator */
- xx->creator.val = (char *)&creater_id;
- xx->account.len = 0; /* File account */
- xx->account.val = "";
- xx->area.len = 0; /* File area */
- xx->area.val = "";
- xx->passwd.len = 0; /* Area password */
- xx->passwd.val = "";
- xx->blksize = -1L; /* File blocksize */
- xx->access.len = 0; /* File access */
- xx->access.val = "";
- xx->encoding.len = 1; /* Transfer syntax */
- xx->encoding.val = "A"; /* ASCII */
- xx->disp.len = 0; /* Disposition upon arrival */
- xx->disp.val = "";
- xx->lprotect.len = sizeof(lclprot); /* Local protection */
- xx->lprotect.val = (char *)&lclprot;
- xx->gprotect.len = sizeof(genprot); /* Generic protection */
- xx->gprotect.val = &genprot;
- xx->systemid.len = 2; /* System ID for DEC/VMS */
- xx->systemid.val = "D7";
- xx->recfm.len = strlen(recfm); /* Record format */
- xx->recfm.val = (char *)&recfm;
- xx->sysparam.len = sysparam_size; /* System-dependent parameters */
- xx->sysparam.val = sysparam_adr;
- xx->length = 1; /* Length */
- return(0); /* mumble sweet nothings at it */
- }
-
- /*
- * Load the generic protection
- */
-
- x = xabpro_ifile.xab$w_pro >> XAB$V_WLD; /* grab returned info */
- if (!(x & XAB$M_NOREAD)) genprot |= 1+32; /* Read access */
- if (!(x & XAB$M_NOWRITE)) genprot |= 2+8; /* Write+Append access */
- if (!(x & XAB$M_NOEXE)) genprot |= 4; /* Execute protection */
- if (!(x & XAB$M_NODEL)) genprot |= 16; /* Delete Access */
- lclprot = xabpro_ifile.xab$w_pro; /* local protection */
-
- /*
- * Convert creation date from an internal value to common ascii string
- */
-
- sys$asctim(&asctim_retlen,&asctim_dsc,&xabdat_ifile.xab$q_cdt,0);
- asctim_buf[asctim_retlen] = '\0';
- debug(F110," zsattr asctim_buf",asctim_buf,0);
- for (x = 0; strncmp(&mth[x],asctim_buf+3,3) ;x++) /* Find month */
- ;
- strncpy(cdate,asctim_buf+7,4); /* 'yyyy' */
- sprintf(cdate+4,"%02d",x+1); /* 'mm' */
- strncpy(cdate+6,asctim_buf+0,2); /* 'dd' */
- strncpy(cdate+8,asctim_buf+11,9); /* ' hh:mm:ss' */
- if (cdate[6] == ' ')
- cdate[6] = '0';
- debug(F110," zsattr cdate",cdate,0);
-
- /*
- * Convert the owner UIC into an alpha name
- */
-
- creater_id[0] = '\0';
- rms_sts = sys$idtoasc(xabpro_ifile.xab$l_uic,&id_len,&id_str,0,0,0);
- creater_id[id_len] = '\0'; /* terminating null, please */
- debug(F111," zsattr $idtoasc owner",creater_id,strlen(creater_id));
- if (rms_sts == SS$_NOSUCHID || rms_sts == SS$_IVIDENT) {
- creater_id[0] = '\0';
- rms_sts = SS$_NORMAL; /* if unknown, null it out */
- }
- if (!(rms_sts & 1)) {
- debug(F101," zsattr $idtoasc failed, status","",rms_sts);
- return(-1); /* fatal */
- }
-
- /*
- * Fill in the record format blockette
- */
-
- if (fab_ifile.fab$b_rat & (FAB$M_CR | FAB$M_FTN | FAB$M_PRN)) {
- strcpy(recfm,"AMJ");
- } else {
- strcpy(recfm,"F");
- sprintf(recfm+1,"%05d",xabfhc_ifile.xab$w_lrl);
- }
- debug(F111," zsattr recfm",recfm,strlen(recfm));
-
- /*
- * Fill in the returned data structure
- */
-
- xx->lengthk = (i+1)/2; /* Number of 1K blocks rounded up */
- xx->type.len = 0; /* File type can't be filled in here */
- xx->type.val = "";
- xx->date.len = strlen(cdate); /* File creation date */
- xx->date.val = (char *)&cdate;
- xx->creator.len = strlen(creater_id); /* File creator */
- xx->creator.val = (char *)&creater_id;
- xx->account.len = 0; /* File account */
- xx->account.val = "";
- xx->area.len = 0; /* File area */
- xx->area.val = "";
- xx->passwd.len = 0; /* Area password */
- xx->passwd.val = "";
- xx->blksize = -1L; /* File blocksize */
- xx->access.len = 0; /* File access */
- xx->access.val = "";
- xx->encoding.len = 1; /* Transfer syntax */
- xx->encoding.val = "A"; /* ASCII */
- xx->disp.len = 0; /* Disposition upon arrival */
- xx->disp.val = "";
- xx->lprotect.len = sizeof(lclprot); /* Local protection */
- xx->lprotect.val = (char *)&lclprot;
- xx->gprotect.len = sizeof(genprot); /* Generic protection */
- xx->gprotect.val = &genprot;
- xx->systemid.len = 2; /* System ID for DEC/VMS */
- xx->systemid.val = "D7";
- xx->recfm.len = strlen(recfm); /* Record format */
- xx->recfm.val = (char *)&recfm;
- xx->sysparam.len = sysparam_size; /* System-dependent parameters */
- xx->sysparam.val = sysparam_adr;
- xx->length = iflen; /* Length */
- return(0);
- }
-
- /* Z M A I L -- Send file f as mail to address p. */
- /*
- Returns 0 on success
- 2 if mail delivered but temp file can't be deleted
- -2 if mail can't be delivered
- */
- int
- zmail(p,f) char *p; char *f; {
- char *zmbuf;
- static char spbuf[] = "$ mail %s %s/subj=\"Enclosed file %s\"";
- static char spbuf2[] = "%s;";
- unsigned long int sts;
-
- zmbuf = malloc(strlen(p)+(2*strlen(f))+sizeof(spbuf));
- sprintf(zmbuf,spbuf, f, p, f);
- sts = system(zmbuf);
- debug(F111," zmail: system returns status ",zmbuf,sts);
- free(zmbuf);
- if ((sts&1) != 1) {
- debug(F101," zmail: returning","",-2);
- return(-2);
- }
- zmbuf = malloc(strlen(f)+sizeof(spbuf2));
- sprintf(zmbuf,spbuf2, f);
- sts = delete(zmbuf);
- debug(F111," zmail: delete returns status ",zmbuf,sts);
- free(zmbuf);
- if (sts) sts = 2;
- debug(F101," zmail: returning","",sts);
- return(sts);
- }
-
- /* Z P R I N T -- Print file f with options p. */
- /*
- Returns 0 on success, -3 on failure.
- */
- int
- zprint(p,f) char *p; char *f; {
- char *zmbuf;
- static char spbuf[] = "$ print/delete %s %s";
- unsigned long int sts;
-
- zmbuf = malloc(strlen(p)+strlen(f)+sizeof(spbuf));
- sprintf(zmbuf,spbuf, p, f);
- sts = system(zmbuf);
- debug(F111," zprint: system returns status ",zmbuf,sts);
- free(zmbuf);
- debug(F101," zprint: returning","",(sts&1) ? 0 : -3);
- return((sts&1) ? 0 : -3);
- }
-
- /* Z S Y S C M D -- Execute a DCL command with direct output. */
-
- /*
- * Since it's really difficult to have an alternate CLI under VMS (since the
- * MCR interface isn't documented and POSIX hasn't published the interface,
- * we'll just assume everybody uses DCL and hand it of to zshcmd().
- */
- int
- zsyscmd(s) char *s; {
- return(zshcmd(s));
- }
-
- /* Z S H C M D -- Execute a default CLI command with direct output. */
-
- /*
- * As it's _REALLY_ unlikely that the user is using MCR as his default CLI,
- * and DEC doesn't document how to write any other alternate CLIs, use DCL.
- */
-
- #ifndef SS$_EXPRCLM /* VMS doesn't return this yet, but let's */
- #define SS$_EXPRCLM 10804 /* be forward-thinking and anticpate VMS */
- #endif /* SS$_EXPRCLM */ /* V6.0, which will return it. */
- int
- zshcmd(s) char *s; {
- unsigned long sts;
- int (*cct)();
- struct dsc$descriptor_s
- cmd_line = {0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0};
-
- if (check_spawn() != 0) {
- debug(F100," zshcmd: spawning prohibited by UAF flags","",0);
- return(0);
- }
-
- cct = signal(SIGINT,SIG_DFL); /* Let inferior process catch ^C */
-
- cmd_line.dsc$w_length = strlen(s);
- cmd_line.dsc$a_pointer = s;
-
- if (!(*s))
- printf("Type LOGOUT to return to VMS C-Kermit.\n\n");
-
- sts = lib$spawn(&cmd_line, 0, 0, 0, 0, 0);
-
- signal(SIGINT,cct);
-
- /*
- * Note: We can't check for this beforehand as doing a getjpi for prclm will
- * only return the UAF value, not the available value. So we try it and
- * print this message if it didn't work.
- */
-
- if ((sts == SS$_EXQUOTA) || (sts == SS$_EXPRCLM)) {
- printf("Your account does not have sufficient quotas to use this \
- command.\n");
- printf("Please ask your system manager to increase your UAF PRCLM \
- quota.\n");
- }
-
- debug(F101,"zshcmd lib$spawn status", "", sts);
- return(0);
- }
-
- /* Z S T R I P -- Strip device & directory name from file specification. */
-
- /* Strip pathname from filename "name", return pointer to result in name2 */
-
- static char work[257]; /* buffer for use by zstrip and zltor */
-
- VOID
- zstrip(name,name2) char *name, **name2; {
- char *cp, *pp;
- debug(F110," zstrip before",name,0);
- pp = work;
-
- /* NODE::DEV:[DIR] terminates on on final ':', '>' or ']'. */
-
- for (cp = name; *cp != '\0'; cp++) {
- if (*cp == '/' || *cp == ':' || *cp == '>' || *cp == ']') /* slash? */
- pp = work;
- else if (*cp == ';') /* Chop off version number */
- break;
- else /* Part of filename */
- *pp++ = *cp;
- }
- *pp = '\0'; /* Terminate the string */
- *name2 = work;
- debug(F110," zstrip after",*name2,0);
- }
-
- int
- zchkpath(s) char *s; {
- /*
- This needs to be replaced with something more intelligent.
- The idea is to see if the file, whose specification is pointed to by s,
- is in the current directory. This function should return 0 if it s,
- nonzero otherwise. Presently we rely on being called with a full
- filespec of the form DISK:[DEV]NAME.TYP;V, so this works more or less
- by accident. What we really need is to call some kind of VMS service
- to get the NODE::DEV:[DIR] of the file, and compare with the current
- NODE::DEV:[DIR].
- */
- char *p;
- p = zgtdir(); /* Get current dir. */
- debug(F110,"zchkpath file",s,0);
- debug(F110,"zchkpath current dir",p,0);
- return(strncmp(p,s,strlen(p))); /* Compare it. */
- }
-
- #ifdef OLD_VMS
- static VOID
- descname(desc,name) struct dsc$descriptor_s *desc; char *name; {
- desc->dsc$w_length = strlen(name); /* Length of name */
- desc->dsc$a_pointer = name; /* Address */
- desc->dsc$b_class = DSC$K_CLASS_S; /* String descriptor class */
- desc->dsc$b_dtype = DSC$K_DTYPE_T; /* ASCII string data type */
- }
-
- /* VMS version of RENAME */
- int /* ? */
- rename(oldname, newname) char oldname[], newname[]; {
- struct dsc$descriptor_s old_desc, new_desc;
- int lib$rename_file();
-
- /* Build string descriptors */
-
- descname(&old_desc, oldname);
- descname(&new_desc, newname);
-
- /* Call lib$rename_file routine */
-
- return(lib$rename_file(&old_desc, &new_desc, 0,0,0,0,0,0,0,0,0,0));
- }
- #endif /* OLD_VMS */
-
- /*
- * Check to see if we have spawn priv's.
- */
- int
- check_spawn() {
- struct itmlstdef {
- short int buflen;
- short int itmcod;
- char *bufaddr;
- long int *retlen;
- };
-
- struct itmlstdef itmlst[] =
- {4,JPI$_UAF_FLAGS,0,0,0,0,0,0};
-
- unsigned long uaf_flags, uaf_flags_size;
-
- itmlst[0].bufaddr = (char *)&uaf_flags;
- itmlst[0].retlen = &uaf_flags_size;
-
- if ((vms_status = sys$getjpiw(0, 0, 0, &itmlst, 0, 0, 0)) != SS$_NORMAL)
- return(-1); /* Assume the worst... */
-
- if (uaf_flags & UAI$M_CAPTIVE) {
- printf("\nThis command cannot be executed. Your account is CAPTIVE.\n\n");
- return(-1);
- }
- #ifdef UAI$M_RESTRICTED /* for pre-V5.2 systems */
- if (uaf_flags & UAI$M_RESTRICTED) {
- printf("\nThis command cannot be executed. Your account is CAPTIVE.\n\n");
- return(-1);
- }
- #endif /* uai$v_restricted */
- return(0);
- }
-
- /*
- * Stuff having to do with SET FILE TYPE LABELED
- */
- char *
- get_vms_vers() {
- static char sysver[9];
- int len;
- struct itmlst {
- short int buflen;
- short int code;
- char *bufadr;
- int *retlen;
- } vms_sysver[2];
-
- vms_sysver[0].buflen = 8;
- vms_sysver[0].code = SYI$_VERSION;
- vms_sysver[0].bufadr = (char *)&sysver;
- vms_sysver[0].retlen = &len;
- vms_sysver[1].buflen = 0;
- vms_sysver[1].code = 0;
- sys$getsyiw(0,0,0,&vms_sysver,0,0,0);
- sysver[8]='\0';
- len = 7;
- while (sysver[len] == ' ') {
- sysver[len] = '\0';
- len--;
- }
- return(sysver);
- }
-
- VOID
- do_label_send(name) char *name; {
- int pad_size;
-
- zinptr += sprintf(zinptr,"KERMIT LABELED FILE:02D704VERS");
- zinptr += sprintf(zinptr,"%08d%s", strlen(get_vms_vers()), get_vms_vers());
- zinptr += sprintf(zinptr,"05KVERS00000008%08d", vernum);
- zinptr += sprintf(zinptr,"07VMSNAME%08d", strlen(name));
- zinptr += sprintf(zinptr,"%s", name);
- zinptr += sprintf(zinptr,"07VMSFILE%08d", 70);
- memmove(zinptr, &xabpro_ifile.xab$w_pro, 2);
- zinptr += 2;
- memmove(zinptr, &xabpro_ifile.xab$l_uic, 4);
- zinptr += 4;
- memmove(zinptr, &fab_ifile.fab$b_rfm, 1);
- zinptr += 1;
- memmove(zinptr, &fab_ifile.fab$b_org, 1);
- zinptr += 1;
- memmove(zinptr, &fab_ifile.fab$b_rat, 1);
- zinptr += 1;
- memmove(zinptr, &uchar, 4); /* Dummy for file chars. */
- zinptr += 4;
- memmove(zinptr, &fab_ifile.fab$b_fsz, 1);
- zinptr += 1;
- memmove(zinptr, &xabfhc_ifile.xab$w_lrl, 2);
- zinptr += 2;
- memmove(zinptr, &fab_ifile.fab$w_mrs, 2);
- zinptr += 2;
- memmove(zinptr, &xabfhc_ifile.xab$l_ebk, 4);
- zinptr += 4;
- memmove(zinptr, &xabfhc_ifile.xab$w_ffb, 2);
- zinptr += 2;
- memmove(zinptr, &xabfhc_ifile.xab$l_hbk, 4);
- zinptr += 4;
- memmove(zinptr, &fab_ifile.fab$w_deq, 2);
- zinptr += 2;
- memmove(zinptr, &fab_ifile.fab$b_bks, 1);
- zinptr += 1;
- memmove(zinptr, &fab_ifile.fab$w_gbc, 2);
- zinptr += 2;
- memmove(zinptr, &xabfhc_ifile.xab$w_verlimit, 2);
- zinptr += 2;
- memmove(zinptr, &fab_ifile.fab$b_rfm+1, 1); /* This is fab$b_journal */
- zinptr += 1;
- memmove(zinptr, &xabdat_ifile.xab$q_cdt, 8);
- zinptr += 8;
- memmove(zinptr, &xabdat_ifile.xab$q_rdt, 8);
- zinptr += 8;
- memmove(zinptr, &xabdat_ifile.xab$w_rvn, 2);
- zinptr += 2;
- memmove(zinptr, &xabdat_ifile.xab$q_edt, 8);
- zinptr += 8;
- memmove(zinptr, &xabdat_ifile.xab$q_bdt, 8);
- zinptr += 8;
- if (xabpro_ifile.xab$w_acllen != 0) {
- zinptr += sprintf(zinptr,"06VMSACL%08d", xabpro_ifile.xab$w_acllen);
- memmove(zinptr, &aclbuf, xabpro_ifile.xab$w_acllen);
- zinptr += xabpro_ifile.xab$w_acllen;
- }
- zinptr += sprintf(zinptr,"04DATA00000000");
- zincnt = (zinptr - zinbuffer); /* Size of this beast */
- zinptr = zinbuffer; /* Reset pointer for readout */
- }
-
- int
- do_label_recv() {
- char *recv_ptr;
- char buffer[16];
- char vmsfile[70];
- char *filptr = vmsfile;
- int lblen;
- int gotname = 0, gotfile = 0, gotacl = 0;
- int i, j;
- unsigned short jnlflg;
-
- debug(F101," in do_label_recv, options","",ofile_lblopts);
- ofile_lblproc = 1; /* Don't come here again */
-
- if (strncmp(zoutbuffer,"KERMIT LABELED FILE:02D704VERS",30) != 0)
- return(0); /* Just continue if unlabeled */
-
- recv_ptr = zoutbuffer+30; /* start at front of buffer */
-
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- lblen = atoi(buffer);
-
- memcpy(buffer, recv_ptr, lblen);
- recv_ptr += lblen;
- buffer[lblen] = '\0';
- debug(F110," file created under VAX/VMS: ",buffer,0);
-
- memcpy(buffer, recv_ptr, 7);
- recv_ptr += 7;
- if (strncmp(buffer, "05KVERS", 7) != 0) {
- debug(F100," lost sync at KVERS","",0);
- return(-1);
- }
-
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- lblen = atoi(buffer);
-
- memcpy(buffer, recv_ptr, lblen);
- recv_ptr += lblen;
- buffer[lblen] = '\0';
- debug(F110," file created with C-Kermit/VMS: ",buffer,0);
-
- next_label:
- memcpy(buffer, recv_ptr, 2);
- recv_ptr += 2;
- buffer[2] = '\0';
- lblen = atoi(buffer);
- if (lblen == 0) {
- debug(F100," lost sync at next_label: ","",0);
- return(-1);
- }
-
- memcpy(buffer, recv_ptr, lblen);
- recv_ptr += lblen;
- buffer[lblen] = '\0';
- debug(F110," found tag: ",buffer,0);
- if (strcmp(buffer, "VMSNAME") == 0) {
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- lblen = atoi(buffer);
- memcpy(ofile_vmsname, recv_ptr, lblen);
- recv_ptr += lblen;
- ofile_vmsname[lblen] = '\0';
- gotname++;
- debug(F110," loaded file name block as: ",ofile_vmsname,0);
- i = strstr(ofile_vmsname, "::");
- if (i != NULL) {
- i += 2;
- memmove(ofile_vmsname, i, strlen(ofile_vmsname));
- }
- if ((ofile_lblopts & LBL_PTH) == 0) {
- i = strrchr(ofile_vmsname, ':');
- j = strrchr(ofile_vmsname, ']');
- if (j == NULL)
- j = strrchr(ofile_vmsname, '>');
- if (j > i)
- i = j;
- i++;
- memmove(ofile_vmsname, i, strlen(ofile_vmsname));
- }
- if (strchr(ofile_vmsname, ';') != NULL) {
- for (j = strlen(ofile_vmsname); ofile_vmsname[j] != ';'; j--)
- ;
- ofile_vmsname[j] = '\0';
- }
- debug(F110," resultant filespec: ",ofile_vmsname,0);
- goto next_label;
- }
- else if (strcmp(buffer, "VMSFILE") == 0) {
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- lblen = atoi(buffer);
- memcpy(vmsfile, recv_ptr, lblen);
- recv_ptr += lblen;
- vmsfile[lblen] = '\0';
- gotfile++;
- debug(F100," loaded file attribute block","",0);
- goto next_label;
- }
- else if (strcmp(buffer, "VMSACL") == 0) {
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- ofile_acllen = atoi(buffer);
- memcpy(ofile_vmsacl, recv_ptr, ofile_acllen);
- recv_ptr += ofile_acllen;
- ofile_vmsacl[ofile_acllen] = '\0';
- gotacl++;
- debug(F100," loaded file ACL block","",0);
- goto next_label;
- }
- else if (strcmp(buffer, "DATA") == 0) {
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- lblen = atoi(buffer);
- if (lblen != 0) {
- debug(F101," length of DATA tag not zero","",lblen);
- return(-1);
- }
- debug(F100," positioned at start of file data","",0);
- goto all_set;
- }
- else {
- debug(F110," unrecognized label: ",buffer,0);
- memcpy(buffer, recv_ptr, 8);
- recv_ptr += 8;
- buffer[8] = '\0';
- lblen = atoi(buffer);
- recv_ptr += lblen;
- goto next_label;
- }
-
- all_set:
- if (gotfile != 1 || gotname != 1) {
- debug(F100," missing one or more required labels","",0);
- return(-1);
- }
-
- /*
- * Prep the characteristics
- */
-
- fab_ofile.fab$b_fac = FAB$M_BIO | FAB$M_PUT;
- fab_ofile.fab$l_fop = FAB$M_MXV;
- if ((ofile_lblopts & LBL_NAM) != 0) {
- fab_ofile.fab$l_fna = ofile_vmsname;
- fab_ofile.fab$b_fns = strlen(ofile_vmsname);
- }
- fab_ofile.fab$l_xab = (char *)&xabdat_ofile;
- rab_ofile = cc$rms_rab;
- rab_ofile.rab$l_fab = &fab_ofile;
- xabdat_ofile = cc$rms_xabdat;
- xabdat_ofile.xab$l_nxt = (char *)&xabrdt_ofile;
- xabrdt_ofile = cc$rms_xabrdt;
- xabrdt_ofile.xab$l_nxt = (char *)&xabfhc_ofile;
- xabfhc_ofile = cc$rms_xabfhc;
- xabfhc_ofile.xab$l_nxt = (char *)&xabpro_ofile;
- xabpro_ofile = cc$rms_xabpro;
- xabpro_ofile.xab$l_nxt = (char *)&xaball_ofile;
- xaball_ofile = cc$rms_xaball;
-
- /*
- * Load 'em up
- */
-
- memmove(&xabpro_ofile.xab$w_pro, filptr, 2);
- filptr += 2;
- if ((ofile_lblopts & LBL_OWN) != 0)
- memmove(&xabpro_ofile.xab$l_uic, filptr, 4);
- filptr += 4;
- memmove(&fab_ofile.fab$b_rfm, filptr, 1);
- filptr += 1;
- memmove(&fab_ofile.fab$b_org, filptr, 1);
- filptr += 1;
- memmove(&fab_ofile.fab$b_rat, filptr, 1);
- filptr += 1;
- filptr += 4; /* reserved */
- memmove(&fab_ofile.fab$b_fsz, filptr, 1);
- filptr += 1;
- memmove(&xabfhc_ofile.xab$w_lrl, filptr, 2);
- filptr += 2;
- memmove(&fab_ofile.fab$w_mrs, filptr, 2);
- filptr += 2;
- memmove(&xabfhc_ofile.xab$l_ebk, filptr, 4);
- filptr += 4;
- /* preserve this as RMS won't remember it for us */
- memmove(&ofile_ffb, filptr, 2);
- filptr += 2;
- memmove(&xaball_ofile.xab$l_alq, filptr, 4);
- filptr += 4;
- memmove(&xaball_ofile.xab$w_deq, filptr, 2);
- filptr += 2;
- memmove(&xaball_ofile.xab$b_bkz, filptr, 1);
- filptr += 1;
- memmove(&fab_ofile.fab$w_gbc, filptr, 2);
- filptr += 2;
- memmove(&xabfhc_ofile.xab$w_verlimit, filptr, 2);
- filptr += 2;
- memmove(&jnlflg, filptr, 1);
- if (jnlflg !=0)
- debug(F100," journaling status removed for file","",0);
- filptr += 1;
- memmove(&xabdat_ofile.xab$q_cdt, filptr, 8);
- filptr += 8;
- memmove(&revdat, filptr, 8);
- filptr += 8;
- memmove(&revnum, filptr, 2);
- filptr += 2;
- memmove(&xabdat_ofile.xab$q_edt, filptr, 8);
- filptr += 8;
- if ((ofile_lblopts & LBL_BCK) != 0)
- memmove(&xabdat_ofile.xab$q_bdt, filptr, 8);
- filptr += 8;
-
- /*
- * ACL's?
- */
-
- if ((ofile_lblopts & LBL_ACL) != 0 && gotacl != 0) {
- xabpro_ofile.xab$l_aclbuf = (char *)&ofile_vmsacl;
- xabpro_ofile.xab$w_aclsiz = ofile_acllen;
- }
-
- /*
- * Give it a quick whirl around the dance floor
- */
-
- rms_sts = sys$create(&fab_ofile);
- if (!(rms_sts & 1)) {
- debug(F101," $create failed, status","",rms_sts);
- return(-1);
- }
-
- if((ofile_lblopts & LBL_ACL) != 0 && gotacl != 0) {
- if (!(xabpro_ofile.xab$l_aclsts & 1)) {
- debug(F101," ACL chain failed, status","",xabpro_ofile.xab$l_aclsts);
- return(-1);
- }
- }
-
- rms_sts = sys$connect(&rab_ofile);
- if (!(rms_sts & 1)) {
- debug(F101," $connect failed, status","",rms_sts);
- return(-1);
- }
-
- /*
- * Slide the remainder of the data to the head of the buffer and adjust the
- * counter and pointer. This will cause the buffer to be re-filled to the full
- * 32Kb capacity, which is necessary for proper operation of zoutdump().
- */
-
- zoutcnt -= ((char *)recv_ptr - (char *)zoutbuffer);
- memcpy(zoutbuffer, recv_ptr, zoutcnt);
- zoutptr = zoutbuffer + zoutcnt;
- return(1); /* Go fill some more */
- }
-